Import Upstream version 1.9.1

This commit is contained in:
su-fang 2022-10-26 16:06:26 +08:00
commit f87f013618
1073 changed files with 487883 additions and 0 deletions

3
.codedocs Normal file
View File

@ -0,0 +1,3 @@
EXCLUDE = addon cmake doc examples jquery templates testing winbuild src/logos.cpp src/lodepng.cpp
FILE_PATTERNS = *.h *.cpp *.md
USE_MDFILE_AS_MAINPAGE = src/doxygen.md

5
.editorconfig Normal file
View File

@ -0,0 +1,5 @@
# See https://editorconfig.org/ for more information.
[*]
indent_style = space
indent_size = 2

View File

@ -0,0 +1,30 @@
---
name: Report a bug or issue
about: Create a report to help us improve doxygen
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
Describe what you see that (you think) is wrong.
**Expected behavior**
Describe what you would have expected or think is correct.
**Screenshots**
If useful, add screenshots to help explain your problem.
**To Reproduce**
Attach a self contained example that allows us to reproduce the problem.
Such an example typically exist of some source code (can be dummy code) and a doxygen configuration file used (you can strip it using `doxygen -s -u`). After you verified the example demonstrates the problem, put it in a zip (or tarball) and attach it to the bug report. Try to avoid linking to external sources, since they might disappear in the future.
**Version**
Mention the version of doxygen used (output of `doxygen --version`) and the platform on which you run doxygen (e.g. Windows 10, 64 bit). If you run doxygen under Linux please also mention the name and version of the distribution used (output of `lsb_release -a`) and mention if you compiled doxygen yourself or that you use a binary that comes with the distribution or from the doxygen website.
**Stack trace**
If you encounter a crash and can build doxygen from sources yourself with debug info (`-DCMAKE_BUILD_TYPE=Debug`), a stack trace can be very helpful (especially if it is not possible to capture the problem in a small example that can be shared).
**Additional context**
Add any other context about the problem here.

360
.github/workflows/build_cmake.yml vendored Normal file
View File

@ -0,0 +1,360 @@
name: CMake Build for Doxygen
on: [push, pull_request]
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Ubuntu Latest GCC Release",
os: ubuntu-18.04,
build_type: "Release", cc: "gcc", cxx: "g++",
build_gen: "Unix Makefiles",
cmake_extra_opts: "-Dbuild_search=YES -Dbuild_app=YES -Dbuild_parse=YES -Dbuild_xmlparser=YES"
}
- {
name: "Ubuntu Latest GCC Debug",
os: ubuntu-18.04,
build_type: "Debug", cc: "gcc", cxx: "g++",
build_gen: "Unix Makefiles",
cmake_extra_opts: "-Dbuild_search=YES -Dbuild_app=YES -Dbuild_parse=YES -Dbuild_xmlparser=YES"
}
- {
name: "Ubuntu Latest Clang Release",
os: ubuntu-20.04,
build_type: "Release", cc: "clang", cxx: "clang++",
build_gen: "Unix Makefiles",
cmake_extra_opts: "-Duse_libclang=YES -Dstatic_libclang=YES -Duse_libc++=NO"
}
- {
name: "Ubuntu Latest Clang Debug",
os: ubuntu-20.04,
build_type: "Debug", cc: "clang", cxx: "clang++",
build_gen: "Unix Makefiles",
cmake_extra_opts: "-Duse_libclang=YES -Dstatic_libclang=YES -Duse_libc++=NO"
}
- {
name: "macOS Latest Release",
os: macos-latest,
build_type: "Release", cc: "clang", cxx: "clang++",
build_gen: "Unix Makefiles"
}
- {
name: "macOS Latest Debug",
os: macos-latest,
build_type: "Debug", cc: "clang", cxx: "clang++",
build_gen: "Unix Makefiles"
}
- {
name: "Windows Latest MSVC Debug",
os: windows-latest,
build_type: "Debug", cc: "cl", cxx: "cl",
build_gen: "NMake Makefiles"
}
- {
name: "Windows Latest MSVC Release",
os: windows-latest,
build_type: "Release", cc: "cl", cxx: "cl",
build_gen: "NMake Makefiles"
}
steps:
- uses: actions/checkout@v1
- name: Download MikTex (Windows)
run: |
$wc = New-Object System.Net.WebClient;
$maxAttempts=5;
$attemptCount=0;
Do {
$attemptCount++;
Try {
$wc.DownloadFile("https://ctan.math.illinois.edu/systems/win32/miktex/setup/windows-x64/miktexsetup-4.0-x64.zip","miktexsetup-4.0-x64.zip")
} Catch [Exception] {
Write-Host $_.Exception | format-list -force
}
} while (((Test-Path "miktexsetup-x64.zip") -eq $false) -and ($attemptCount -le $maxAttempts))
shell: pwsh
if: matrix.config.os == 'windows-latest'
- uses: suisei-cn/actions-download-file@v1
with:
url: "https://github.com/pffang/libiconv-for-Windows/releases/download/v1.16/libiconv-for-Windows_1.16.7z"
target: .
if: matrix.config.os == 'windows-latest'
- name: Install LaTeX (Linux)
run: sudo apt-get install texlive texlive-latex-recommended texlive-extra-utils texlive-latex-extra texlive-font-utils
if: startsWith(matrix.config.os,'ubuntu-')
- name: Install LaTeX (MacOS)
run: |
brew install --cask mactex;
echo "/Library/TeX/texbin/" >> $GITHUB_PATH
if: matrix.config.os == 'macos-latest'
- name: Install libclang (Ubuntu 20.04)
run: |
sudo apt remove llvm-8 clang-8 libclang-common-8-dev clang-format-8 libllvm8
#sudo apt remove llvm-10 llvm-10-dev llvm-10-tools llvm-10-runtime clang-10 clang-format-10 libclang-common-10-dev libclang-cpp10 libclang1-10 libllvm10
sudo apt-get autoremove
sudo apt-get clean
#sudo apt install libclang-9-dev libclang-common-9-dev
sudo apt install libclang-10-dev libclang-common-10-dev
apt list --installed | egrep '(clang|llvm)'
ls -d /usr/lib/llvm-*/include/
clang++ -v
if: matrix.config.os == 'ubuntu-20.04'
- name: Install libxapian (Ubuntu 18.04)
run: |
sudo apt install libxapian-dev
if: matrix.config.os == 'ubuntu-18.04'
- name: Extract MikTex zip (Windows)
shell: bash
run: |
unzip miktexsetup-4.0-x64.zip
if: matrix.config.os == 'windows-latest'
- name: Download MikTex packages (Windows)
shell: bash
run: |
./miktexsetup --verbose \
--local-package-repository=C:/miktex-repository \
--remote-package-repository="https://ctan.math.illinois.edu/systems/win32/miktex/tm/packages/" \
--package-set=essential \
download
if: matrix.config.os == 'windows-latest'
- name: Install MikTex packages (Windows)
shell: bash
run: |
./miktexsetup --local-package-repository=C:/miktex-repository \
--package-set=essential \
--shared \
install
if: matrix.config.os == 'windows-latest'
- name: Setting MikTex paths (Windows)
shell: bash
run: |
echo "C:/Program Files/MiKTeX/miktex/bin/x64/" >> $GITHUB_PATH
export PATH="/c/Program Files/MiKTeX/miktex/bin/x64/:$PATH"
echo "Configuring MiKTeX to install missing packages on the fly"
initexmf --admin --verbose --set-config-value='[MPM]AutoInstall=1'
if: matrix.config.os == 'windows-latest'
- name: Install Ghostscript (Linux)
run: sudo apt-get install ghostscript
if: startsWith(matrix.config.os,'ubuntu-')
- name: Install Ghostscript (Windows)
run:
choco install ghostscript
if: matrix.config.os == 'windows-latest'
- name: Setting Ghostscript paths (Windows)
shell: bash
run: |
echo "C:/Program Files (x86)/gs/gs9.53.3/bin/" >> $GITHUB_PATH
echo "C:/Program Files/gs/gs9.53.3/bin/" >> $GITHUB_PATH
export PATH="/c/Program Files (x86)/gs/gs9.53.3/bin/:$PATH"
export PATH="/c/Program Files/gs/gs9.53.3/bin/:$PATH"
if: matrix.config.os == 'windows-latest'
- name: Install xmllint (Linux)
run: sudo apt-get install libxml2-utils
if: startsWith(matrix.config.os,'ubuntu-')
- name: Install xmllint (MacOS)
run: brew install libxml2
if: matrix.config.os == 'macos-latest'
- name: Install bison (MacOS)
run: |
brew install bison;
echo "/usr/local/opt/bison/bin" >> $GITHUB_PATH
if: matrix.config.os == 'macos-latest'
- name: Install bison/flex (Windows)
run:
choco install winflexbison
if: matrix.config.os == 'windows-latest'
- name: Install Graphviz (Linux)
run: sudo apt-get install graphviz
if: startsWith(matrix.config.os,'ubuntu-')
- name: Install Graphviz (MacOS)
run: brew install graphviz
if: matrix.config.os == 'macos-latest'
- name: Install Graphviz (Windows)
run:
choco install graphviz.portable
if: matrix.config.os == 'windows-latest'
# - name: Install Perl (Windows)
# run:
# choco install activeperl
# if: matrix.config.os == 'windows-latest'
- name: Setup VS Environment (Windows)
uses: seanmiddleditch/gha-setup-vsdevenv@master
if: matrix.config.os == 'windows-latest'
- name: Refresh Env (Windows)
run:
refreshenv
if: matrix.config.os == 'windows-latest'
- name: Install Qt
uses: jurplel/install-qt-action@v2
- name: Check tool versions (Linux / MacOS)
shell: bash
run: |
echo "=== perl ===";
perl --version;
echo "=== python ===";
python --version;
echo "=== cmake ===";
cmake --version;
echo "=== latex ===";
latex --version;
echo "=== bibtex ===";
bibtex --version
echo "=== dvips ===";
dvips --version
echo "=== bison ===";
bison --version;
echo "=== flex ===";
flex --version;
echo "=== dot ===";
dot -V;
echo "=== ghostscript ===";
gs --version;
if: matrix.config.os != 'windows-latest'
- name: Check tool versions (Windows)
shell: bash
run: |
echo "=== perl ===";
perl --version;
echo "=== python ===";
python --version;
echo "=== cmake ===";
cmake --version;
echo "=== latex ===";
latex --version;
echo "=== bibtex ===";
bibtex --version
echo "=== dvips ===";
dvips --version
echo "=== bison ===";
win_bison --version;
echo "=== flex ===";
win_flex --version;
echo "=== dot ===";
dot -V;
echo "=== ghostscript ===";
gswin64c --version;
if: matrix.config.os == 'windows-latest'
- name: Configure
shell: cmake -P {0}
run: |
set(ENV{CC} ${{ matrix.config.cc }})
set(ENV{CXX} ${{ matrix.config.cxx }})
execute_process(
COMMAND cmake
-S .
-B build
-D CMAKE_BUILD_TYPE=${{ matrix.config.build_type }}
-G "${{ matrix.config.build_gen }}"
-Dbuild_doc=YES
-Dbuild_wizard=YES
${{ matrix.config.cmake_extra_opts }}
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Bad exit status")
endif()
- name: Build
shell: cmake -P {0}
run: |
include(ProcessorCount)
ProcessorCount(N)
execute_process(
COMMAND cmake --build build --parallel ${N}
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE output
ECHO_OUTPUT_VARIABLE ECHO_ERROR_VARIABLE
)
if (NOT result EQUAL 0)
string(REGEX MATCH "FAILED:.*$" error_message "${output}")
string(REPLACE "\n" "%0A" error_message "${error_message}")
message("::error::${error_message}")
message(FATAL_ERROR "Build failed")
endif()
- name: Archive build artifacts
uses: actions/upload-artifact@v2
with:
name: "${{ matrix.config.name }} build artifacts"
path: build/bin/
- name: Run tests (Linux / MacOS)
shell: cmake -P {0}
run: |
include(ProcessorCount)
ProcessorCount(N)
set(ENV{CTEST_OUTPUT_ON_FAILURE} "ON")
execute_process(
COMMAND cmake --build build --target tests TEST_FLAGS="--xml --xmlxsd --xhtml --docbook --rtf"
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Running tests failed!")
endif()
if: matrix.config.os != 'windows-latest'
- name: Run tests (Windows)
shell: cmake -P {0}
run: |
include(ProcessorCount)
ProcessorCount(N)
set(ENV{CTEST_OUTPUT_ON_FAILURE} "ON")
execute_process(
COMMAND cmake --build build --target tests TEST_FLAGS="--xml --xmlxsd"
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Running tests failed!")
endif()
if: matrix.config.os == 'windows-latest'
- name: Generate documentation
shell: cmake -P {0}
run: |
execute_process(
COMMAND cmake --build build --target docs
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Building documentation failed")
endif()
if: matrix.config.os != 'windows-latest'

20
.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
*~
.*sw?
\#*
.DS_Store
*.rej
*.orig
*.pro
/packages/rpm/doxygen.spec
*.idb
*.pdb
/doxygen_docs
/doxygen.tag
/build*
tags
.idea

1
.pc/.quilt_patches Normal file
View File

@ -0,0 +1 @@
debian/patches

1
.pc/.quilt_series Normal file
View File

@ -0,0 +1 @@
series

1
.pc/.version Normal file
View File

@ -0,0 +1 @@
2

10
.pc/applied-patches Normal file
View File

@ -0,0 +1,10 @@
manpages.diff
dot-config.diff
no-timestamps.diff
avoid-compass.diff
fix-pdflatex-invocation.diff
faketime_pdflatex.diff
libatomic.diff
reproducible_changelog.diff
reproducible_manpages.diff
sass_fix.diff

View File

@ -0,0 +1,38 @@
JQUERY_VERSION = 3.4.1
JQUERY_UI_VERSION = 1.12.1
SCROLL_VERSION = 2.1.2
POWERTIP_VERSION = 1.3.1
TOUCHPUNCH_VERSION = 0.2.3
SMARTMENUS_VERSION = 1.1.0
MINIFIER ?= /usr/local/bin/yuicompressor-2.4.7
SCRIPTS = jquery-$(JQUERY_VERSION).min.js \
jquery.ui-$(JQUERY_UI_VERSION).min.js \
jquery.scrollTo-$(SCROLL_VERSION).min.js \
jquery.powertip-$(POWERTIP_VERSION).mod.min.js \
jquery.ui.touch-punch-$(TOUCHPUNCH_VERSION).min.js \
jquery.smartmenus-$(SMARTMENUS_VERSION).min.js
RESULTS = jquery.js doxmenu-min.css
all: $(RESULTS)
install: $(RESULTS)
cp jquery.js ../templates/html/jquery.js
cp doxmenu-min.css ../templates/html/tabs.css
jquery.js: $(SCRIPTS)
cat $(SCRIPTS) > jquery.js
doxmenu-min.css: sm-core-css.css \
sass/sm-dox.scss \
sass/_round-corners-last-item.scss \
sass/_sm-dox.scss \
sass/_sub-items-indentation.scss
compass compile --css-dir . --force sass/sm-dox.scss
cat sm-core-css.css sm-dox.css > doxmenu.css
java -jar $(MINIFIER).jar doxmenu.css > doxmenu-min.css
rm -f sm-dox.css doxmenu.css
clean:
rm -rf $(RESULTS) doxmenu.css .sass-cache

View File

@ -0,0 +1,23 @@
// Generate rules to round the corners of the last collapsible item
@mixin sm-dox__round-corners-last-item($amount, $chainable: 'ul > li:last-child > ', $level: 4, $chain_prefix: '> li:last-child > ', $chain: '', $selector: '') {
$chain: $chain_prefix;
$selector: $chain + 'a, ' + $chain + '*:not(ul) a, ' + $chain + 'ul';
@for $i from 1 through $level {
$chain: $chain + $chainable;
$selector: $selector + ', ' + $chain + ' a, ' + $chain + '*:not(ul) a, ' + $chain + ' ul';
}
#{$selector} {
@include border-radius(0 0 $amount $amount);
}
// highlighted items, don't need rounding since their sub is open
$chain: $chain_prefix;
$selector: $chain + 'a.highlighted, ' + $chain + '*:not(ul) a.highlighted';
@for $i from 1 through $level {
$chain: $chain + $chainable;
$selector: $selector + ', ' + $chain + ' a.highlighted, ' + $chain + '*:not(ul) a.highlighted';
}
#{$selector} {
@include border-radius(0);
}
}

View File

@ -0,0 +1,594 @@
@import 'compass';
// This file is best viewed with Tab size 4 code indentation
// -----------------------------------------------------------------------------------------------------------------
// 1. Theme Quick Settings (Variables)
// (for further control, you will need to dig into the actual CSS in 2.)
// -----------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------
// :: 1.1. Colors
// ----------------------------------------------------------
$sm-dox__white: #fff !default;
$sm-dox__gray: darken($sm-dox__white, 6.5%) !default;
$sm-dox__gray-dark: darken($sm-dox__white, 26.5%) !default;
$sm-dox__gray-darker: darken($sm-dox__white, 66.5%) !default;
$sm-dox__red: #D23600 !default;
$sm-dox__box-shadow: rgba(0, 0, 0, 0.2) !default;
// ----------------------------------------------------------
// :: 1.2. Breakpoints
// ----------------------------------------------------------
$sm-dox__desktop-vp: 768px !default; // switch from collapsible to desktop
// ----------------------------------------------------------
// :: 1.3. Typography
// ----------------------------------------------------------
$sm-dox__font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif !default;
$sm-dox__font-size-base: 13px !default;
$sm-dox__font-size-small: 12px !default;
$sm-dox__line-height: 15px !default;
// ----------------------------------------------------------
// :: 1.4. Borders
// ----------------------------------------------------------
$sm-dox__border-width: 1px !default;
$sm-dox__border-radius: 5px !default;
// ----------------------------------------------------------
// :: 1.5. Collapsible main menu
// ----------------------------------------------------------
// Menu box
//$sm-dox__collapsible-bg: $sm-dox__gray !default;
$sm-dox__collapsible-bg: url('tab_b.png') !default;
$sm-dox__collapsible-border-radius: $sm-dox__border-radius !default;
// Items
$sm-dox__collapsible-item-color: $sm-dox__gray-darker !default;
$sm-dox__collapsible-item-current-color: $sm-dox__red !default;
$sm-dox__collapsible-item-disabled-color: darken($sm-dox__gray, 20%) !default;
$sm-dox__collapsible-item-padding-vertical: 0px !default;
$sm-dox__collapsible-item-padding-horizontal: 12px !default;
// Items separators
$sm-dox__collapsible-separators-color: rgba(0, 0, 0, 0.05) !default;
// Toggle button (sub menu indicators)
$sm-dox__collapsible-toggle-bg: rgba(255, 255, 255, 0.5) !default;
// ----------------------------------------------------------
// :: 1.6. Collapsible sub menus
// ----------------------------------------------------------
// Menu box
$sm-dox__collapsible-sub-bg: rgba(darken($sm-dox__gray, 30%), 0.1) !default;
// Items text indentation for deeper levels
$sm-dox__collapsible-sub-item-indentation: 8px !default;
// ----------------------------------------------------------
// :: 1.7. Desktop main menu
// ----------------------------------------------------------
// Menu box
//$sm-dox__desktop-bg: $sm-dox__gray !default;
$sm-dox__desktop-bg: url('tab_b.png') !default;
//$sm-dox__desktop-border-radius: 100px !default;
$sm-dox__desktop-padding-horizontal: 10px !default;
// Items
$sm-dox__desktop-item-color: $sm-dox__gray_darker !default;
$sm-dox__desktop-item-hover-color: $sm-dox__red !default;
$sm-dox__desktop-item-current-color: $sm-dox__red !default;
$sm-dox__desktop-item-disabled-color: darken($sm-dox__gray, 20%) !default;
$sm-dox__desktop-item-padding-vertical: 0px !default;
$sm-dox__desktop-item-padding-horizontal: 12px !default;
// Sub menu indicators
$sm-dox__desktop-arrow-size: 4px !default; // border-width
$sm-dox__desktop-arrow-color: $sm-dox__gray-darker !default;
$sm-dox__desktop-arrow-spacing: 4px !default;
// Vertical menu box
$sm-dox__desktop-vertical-border-radius: $sm-dox__border-radius !default;
$sm-dox__desktop-vertical-padding-vertical: 10px !default;
// Vertical items
$sm-dox__desktop-vertical-item-hover-bg: $sm-dox__white !default;
$sm-dox__desktop-vertical-item-padding-vertical: 10px !default;
$sm-dox__desktop-vertical-item-padding-horizontal: 20px !default;
$sm-dox__main-text-color: #283A5D !default;
$sm-dox__main-highlight-color: white !default;
// ----------------------------------------------------------
// :: 1.8. Desktop sub menus
// ----------------------------------------------------------
// Menu box
$sm-dox__desktop-sub-bg: $sm-dox__white !default;
$sm-dox__desktop-sub-border-color: $sm-dox__gray-dark !default;
$sm-dox__desktop-sub-border-radius: $sm-dox__border-radius !default;
$sm-dox__desktop-sub-box-shadow: 0 5px 9px $sm-dox__box-shadow !default;
$sm-dox__desktop-sub-padding-vertical: 5px !default;
$sm-dox__desktop-sub-padding-horizontal: 0 !default;
// Items
$sm-dox__desktop-sub-item-color: $sm-dox__gray_darker !default;
$sm-dox__desktop-sub-item-hover-color: $sm-dox__red !default;
$sm-dox__desktop-sub-item-hover-bg: $sm-dox__gray !default;
$sm-dox__desktop-sub-item-current-color: $sm-dox__red !default;
$sm-dox__desktop-sub-item-disabled-color: darken($sm-dox__white, 20%) !default;
$sm-dox__desktop-sub-item-padding-vertical: 10px !default;
$sm-dox__desktop-sub-item-padding-horizontal: 20px !default;
// Sub menu indicators
$sm-dox__desktop-sub-arrow-size: 5px !default; // border-width
// Sub menu carets
$sm-dox__desktop-sub-caret-size: 8px !default; // border-width
$sm-dox__desktop-sub-caret-left: 30px !default;
$sm-dox__main-row-height: 36px !default;
// -----------------------------------------------------------------------------------------------------------------
// 2. Theme CSS
// -----------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------
// :: 2.1. Collapsible mode (mobile first)
// ----------------------------------------------------------
// calc item height and sub menus toggle button size
$sm-dox__item-height: $sm-dox__line-height + $sm-dox__collapsible-item-padding-vertical * 2;
// set toggle button size to 80% of item height
$sm-dox__toggle-size: floor($sm-dox__main-row-height * 0.8);
$sm-dox__toggle-spacing: floor($sm-dox__main-row-height * 0.1);
// Main menu box
.sm-dox {
background-image: $sm-dox__collapsible-bg;
//@include border-radius($sm-dox__collapsible-border-radius);
// Main menu items
a {
&,
&:focus,
&:hover,
&:active {
padding: $sm-dox__collapsible-item-padding-vertical $sm-dox__collapsible-item-padding-horizontal;
/* make room for the toggle button (sub indicator) */
padding-right: $sm-dox__collapsible-item-padding-horizontal + $sm-dox__toggle-size + $sm-dox__toggle-spacing;
/* color: $sm-dox__collapsible-item-color; */
font-family: $sm-dox__font-family;
font-size: $sm-dox__font-size-base;
font-weight: bold;
line-height: 36px; //$sm-dox__line-height;
text-decoration: none;
text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
color: $sm-dox__main-text-color;
outline: none;
}
&:hover {
background-image: url('tab_a.png');
background-repeat:repeat-x;
color: $sm-dox__main-highlight-color;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
}
&.current {
color: $sm-dox__collapsible-item-current-color;
}
&.disabled {
color: $sm-dox__collapsible-item-disabled-color;
}
// Toggle buttons (sub menu indicators)
span.sub-arrow {
position: absolute;
top: 50%;
margin-top: -(ceil($sm-dox__toggle-size / 2));
left: auto;
right: $sm-dox__toggle-spacing;
width: $sm-dox__toggle-size;
height: $sm-dox__toggle-size;
overflow: hidden;
font: bold #{$sm-dox__font-size-small}/#{$sm-dox__toggle-size} monospace !important;
text-align: center;
text-shadow: none;
background: $sm-dox__collapsible-toggle-bg;
@include border-radius($sm-dox__border-radius);
}
// Change + to - on sub menu expand
&.highlighted span.sub-arrow:before {
display: block;
content: '-';
}
}
// round the corners of the first item
> li:first-child > a, > li:first-child > :not(ul) a {
@include border-radius($sm-dox__collapsible-border-radius $sm-dox__collapsible-border-radius 0 0);
}
// round the corners of the last item
@include sm-dox__round-corners-last-item($sm-dox__collapsible-border-radius);
// Main menu items separators
//li {
// /*border-top: 1px solid $sm-dox__collapsible-separators-color;*/
// border-top: 0;
//}
//> li:first-child {
// border-top: 0;
//}
// Sub menus box
ul {
background: $sm-dox__collapsible-sub-bg;
// Sub menus items
a {
&,
&:focus,
&:hover,
&:active {
font-size: $sm-dox__font-size-small;
// add indentation for sub menus text
border-left: $sm-dox__collapsible-sub-item-indentation solid transparent;
//line-height: $sm-dox__line-height;
line-height: $sm-dox__main-row-height;
text-shadow: none;
background-color: white;
background-image: none;
}
&:hover {
// color: $sm-dox__collapsible-item-current-color;
// background-color: $sm-dox__gray;
background-image: url('tab_a.png');
background-repeat:repeat-x;
color: $sm-dox__main-highlight-color;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
}
}
// Add indentation for sub menus text for deeper levels
@include sm-dox__sub-items-indentation($sm-dox__collapsible-sub-item-indentation);
}
}
// ----------------------------------------------------------
// :: 2.2. Desktop mode
// ----------------------------------------------------------
@media (min-width: $sm-dox__desktop-vp) {
/* Switch to desktop layout
-----------------------------------------------
These transform the menu tree from
collapsible to desktop (navbar + dropdowns)
-----------------------------------------------*/
/* start... (it's not recommended editing these rules) */
.sm-dox ul{position:absolute;width:12em;}
.sm-dox li{float:left;}
.sm-dox.sm-rtl li{float:right;}
.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none;}
.sm-dox a{white-space:nowrap;}
.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal;}
.sm-dox .sm-nowrap > li > a,.sm-dox .sm-nowrap > li > :not(ul) a{white-space:nowrap;}
/* ...end */
// Main menu box
.sm-dox {
padding: 0 $sm-dox__desktop-padding-horizontal;
background-image: $sm-dox__desktop-bg;
line-height: 36px;
//@include border-radius($sm-dox__desktop-border-radius);
// Main menu items
a {
// Sub menu indicators
span.sub-arrow {
top: 50%;
margin-top: -(ceil($sm-dox__desktop-arrow-size / 2));
right: $sm-dox__desktop-item-padding-horizontal;
width: 0;
height: 0;
border-width: $sm-dox__desktop-arrow-size;
border-style: solid dashed dashed dashed;
border-color: $sm-dox__main-text-color transparent transparent transparent;
background: transparent;
@include border-radius(0);
}
&,
&:focus,
&:active,
&:hover,
&.highlighted {
padding: $sm-dox__desktop-item-padding-vertical $sm-dox__desktop-item-padding-horizontal;
/*color: $sm-dox__desktop-item-color;*/
background-image:url('tab_s.png');
background-repeat:no-repeat;
background-position:right;
@include border-radius(0 !important);
}
&:hover {
background-image: url('tab_a.png');
background-repeat:repeat-x;
color: $sm-dox__main-highlight-color;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
span.sub-arrow {
border-color: $sm-dox__main-highlight-color transparent transparent transparent;
}
}
// Make room for the sub arrows
&.has-submenu {
padding-right: $sm-dox__desktop-item-padding-horizontal + $sm-dox__desktop-arrow-size * 2 + $sm-dox__desktop-arrow-spacing;
}
}
// No main menu items separators
li {
border-top: 0;
}
// First sub level carets
> li > ul:before,
> li > ul:after {
content: '';
position: absolute;
top: -($sm-dox__desktop-sub-caret-size * 2 + $sm-dox__border-width * 2);
left: $sm-dox__desktop-sub-caret-left;
width: 0;
height: 0;
overflow: hidden;
border-width: ($sm-dox__desktop-sub-caret-size + $sm-dox__border-width);
border-style: dashed dashed solid dashed;
border-color: transparent transparent $sm-dox__gray-dark transparent;
}
> li > ul:after {
top: -($sm-dox__desktop-sub-caret-size * 2);
left: ($sm-dox__desktop-sub-caret-left + $sm-dox__border-width);
border-width: $sm-dox__desktop-sub-caret-size;
border-color: transparent transparent $sm-dox__desktop-sub-bg transparent;
}
// Sub menus box
ul {
border: $sm-dox__border-width solid $sm-dox__gray-dark;
padding: $sm-dox__desktop-sub-padding-vertical $sm-dox__desktop-sub-padding-horizontal;
background: $sm-dox__desktop-sub-bg;
@include border-radius($sm-dox__desktop-sub-border-radius !important);
@include box-shadow($sm-dox__desktop-sub-box-shadow);
// Sub menus items
a {
span.sub-arrow {
right: 8px;
top: 50%;
margin-top: -$sm-dox__desktop-sub-arrow-size;
border-width: $sm-dox__desktop-sub-arrow-size;
border-color: transparent transparent transparent $sm-dox__desktop-sub-item-color;
border-style: dashed dashed dashed solid;
}
&,
&:hover,
&:focus,
&:active,
&.highlighted {
color: $sm-dox__desktop-sub-item-color;
background-image:none;
border: 0 !important;
color: $sm-dox__desktop-sub-item-color;
background-image:none;
}
&:hover {
background-image: url('tab_a.png');
background-repeat:repeat-x;
color: $sm-dox__main-highlight-color;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
span.sub-arrow {
border-color: transparent transparent transparent $sm-dox__main-highlight-color;
}
}
}
}
// Scrolling arrows containers for tall sub menus - test sub menu: "Sub test" -> "more..." in the default download package
span.scroll-up,
span.scroll-down {
position: absolute;
display: none;
visibility: hidden;
overflow: hidden;
background: $sm-dox__desktop-sub-bg;
height: 36px;
// width and position will be set automatically by the script
&:hover {
background: $sm-dox__desktop-sub-item-hover-bg;
}
}
span.scroll-up:hover span.scroll-up-arrow {
border-color: transparent transparent $sm-dox__desktop-sub-item-hover-color transparent;
}
span.scroll-down:hover span.scroll-down-arrow {
border-color: $sm-dox__desktop-sub-item-hover-color transparent transparent transparent;
}
span.scroll-up-arrow {
position: absolute;
top: 0;
left: 50%;
margin-left: -6px;
// we will use one-side border to create a triangle so that we don't use a real background image, of course, you can use a real image if you like too
width: 0;
height: 0;
overflow: hidden;
border-width: 6px; // tweak size of the arrow
border-style: dashed dashed solid dashed;
border-color: transparent transparent $sm-dox__desktop-sub-item-color transparent;
}
span.scroll-down-arrow {
@extend span.scroll-up-arrow;
top: 8px;
border-style: solid dashed dashed dashed;
border-color: $sm-dox__desktop-sub-item-color transparent transparent transparent;
}
// Rigth-to-left
// Main menu box
&.sm-rtl {
// Main menu items
a {
// Make room for the sub arrows
&.has-submenu {
padding-right: $sm-dox__desktop-item-padding-horizontal;
padding-left: $sm-dox__desktop-item-padding-horizontal + $sm-dox__desktop-arrow-size * 2 + $sm-dox__desktop-arrow-spacing;
}
// Sub menu indicators
span.sub-arrow {
right: auto;
left: $sm-dox__desktop-item-padding-horizontal;
}
}
// Vertical main menu items
&.sm-vertical {
a {
// No need for additional room for the sub arrows
&.has-submenu {
padding: $sm-dox__desktop-vertical-item-padding-vertical $sm-dox__desktop-vertical-item-padding-horizontal;
}
// Sub menu indicators
span.sub-arrow {
right: auto;
left: 8px;
border-style: dashed solid dashed dashed;
border-color: transparent $sm-dox__desktop-arrow-color transparent transparent;
}
}
}
// First sub level carets
> li > ul:before {
left: auto;
right: $sm-dox__desktop-sub-caret-left;
}
> li > ul:after {
left: auto;
right: ($sm-dox__desktop-sub-caret-left + $sm-dox__border-width);
}
// Sub menus box
ul {
a {
// No need for additional room for the sub arrows
&.has-submenu {
padding: $sm-dox__desktop-sub-item-padding-vertical $sm-dox__desktop-sub-item-padding-horizontal !important;
}
// Sub menu indicators
span.sub-arrow {
right: auto;
left: 8px;
border-style: dashed solid dashed dashed;
border-color: transparent $sm-dox__desktop-arrow-color transparent transparent;
}
}
}
}
// Vertical main menu
// Main menu box
&.sm-vertical {
padding: $sm-dox__desktop-vertical-padding-vertical 0;
@include border-radius($sm-dox__desktop-vertical-border-radius);
// Main menu items
a {
padding: $sm-dox__desktop-vertical-item-padding-vertical $sm-dox__desktop-vertical-item-padding-horizontal;
&:hover,
&:focus,
&:active,
&.highlighted {
background: $sm-dox__desktop-vertical-item-hover-bg;
}
&.disabled {
background-image: $sm-dox__desktop-bg;
}
// Sub menu indicators
span.sub-arrow {
right: 8px;
top: 50%;
margin-top: -$sm-dox__desktop-sub-arrow-size;
border-width: $sm-dox__desktop-sub-arrow-size;
border-style: dashed dashed dashed solid;
border-color: transparent transparent transparent $sm-dox__desktop-arrow-color;
}
}
// No sub level carets
> li > ul:before,
> li > ul:after {
display: none;
}
// Sub menus box
ul {
// Sub menus items
a {
padding: $sm-dox__desktop-sub-item-padding-vertical $sm-dox__desktop-sub-item-padding-horizontal;
&:hover,
&:focus,
&:active,
&.highlighted {
background: $sm-dox__desktop-sub-item-hover-bg;
}
&.disabled {
background: $sm-dox__desktop-sub-bg;
}
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,271 @@
# vim:ts=4:sw=4:expandtab:autoindent:
#
# Copyright (C) 1997-2015 by Dimitri van Heesch.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation under the terms of the GNU General Public License is hereby
# granted. No representations are made about the suitability of this software
# for any purpose. It is provided "as is" without express or implied warranty.
# See the GNU General Public License for more details.
#
# Documents produced by Doxygen are derivative works derived from the
# input used in their production; they are not affected by this license.
include (${TOP}/cmake/version.cmake)
string(TIMESTAMP DATE "%d-%m-%Y")
find_package(PythonInterp REQUIRED)
find_program(EPSTOPDF NAMES epstopdf )
find_program(PDFLATEX NAMES pdflatex )
find_program(MAKEINDEX NAMES makeindex )
include(GNUInstallDirs)
if (doxygen_BINARY_DIR)
set(DOXYGEN_EXECUTABLE ${doxygen_BINARY_DIR}/bin/doxygen)
else()
# when building only the doxygen_doc, from the doc/ directory, the
# doxygen project variables are unknown so look for doxygen in PATH
find_package(Doxygen)
endif()
set(DOC_INSTALL_DIR "share/doc/packages/doxygen" CACHE STRING "Relative path where to install the documentation")
set(DOC_FILES
arch.doc
archoverview.eps
archoverview.svg
autolink.doc
changelog.doc
commands.doc
custcmd.doc
customize.doc
diagrams.doc
docblocks.doc
Doxyfile
doxygen_manual.css
doxygen_usage.doc
doxywizard_expert.png
doxywizard_main.png
doxywizard_menu_file.png
doxywizard_menu_settings.png
doxywizard_menu_help.png
doxywizard_page1.png
doxywizard_page2.png
doxywizard_page3.png
doxywizard_page4.png
doxywizard_run.png
doxywizard_usage.doc
expert_bool.png
expert_enum.png
expert_int.png
expert_list_dir.png
expert_list_file.png
expert_list_filedir.png
expert_list_string.png
expert_string_dir.png
expert_string_file.png
expert_string_image.png
expert_string_string.png
external.doc
extsearch.doc
extsearch_flow.dot
extsearch_flow.eps
extsearch_flow.png
faq.doc
features.doc
formulas.doc
tables.doc
grouping.doc
htmlcmds.doc
index.doc
index.hhp.txt
infoflow.eps
infoflow.fig
infoflow.png
install.doc
install_prefix
lists.doc
markdown.doc
output.doc
perlmod.doc
perlmod_tree.doc
preprocessing.doc
searching.doc
starting.doc
trouble.doc
xmlcmds.doc
emojisup.doc
language.tpl
maintainers.txt
translator.py
smile.png
doxygen_logo.svg
)
set(DOC_FILES_IMAGES
add.png
del.png
file.png
folder.png
refresh.png
)
if (build_doc_chm)
set(DOC_FILES_CHM
Doxyfile_chm
)
endif ()
if (${CMAKE_VERSION} VERSION_EQUAL "3.11.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.11.0")
file(GLOB LANG_FILES CONFIGURE_DEPENDS "${TOP}/src//translator_??.h")
else()
file(GLOB LANG_FILES "${TOP}/src//translator_??.h")
endif()
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/man
${PROJECT_BINARY_DIR}/src
${PROJECT_BINARY_DIR}/doc
${PROJECT_BINARY_DIR}/doc/images)
foreach (f ${DOC_FILES})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/
DEPENDS ${PROJECT_SOURCE_DIR}/doc/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_FILES "${PROJECT_BINARY_DIR}/doc/${f}")
endforeach()
foreach (f ${DOC_FILES_IMAGES})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/images/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/addon/doxywizard/images/${f} ${PROJECT_BINARY_DIR}/doc/images/
DEPENDS ${PROJECT_SOURCE_DIR}/addon/doxywizard/images/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/images/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_FILES "${PROJECT_BINARY_DIR}/doc/images/${f}")
endforeach()
foreach (f ${DOC_FILES_CHM})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/
DEPENDS ${PROJECT_SOURCE_DIR}/doc/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_CHM_FILES "${PROJECT_BINARY_DIR}/doc/${f}")
endforeach()
configure_file(${PROJECT_SOURCE_DIR}/doc/manual.sty ${PROJECT_BINARY_DIR}/doc/manual.sty)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen_manual.tex ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen.1 ${PROJECT_BINARY_DIR}/man/doxygen.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxywizard.1 ${PROJECT_BINARY_DIR}/man/doxywizard.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxysearch.1 ${PROJECT_BINARY_DIR}/man/doxysearch.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxyindexer.1 ${PROJECT_BINARY_DIR}/man/doxyindexer.1)
# doc/language.doc (see tag Doxyfile:INPUT)
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} translator.py ${PROJECT_SOURCE_DIR}
DEPENDS ${PROJECT_SOURCE_DIR}/doc/maintainers.txt ${PROJECT_SOURCE_DIR}/doc/language.tpl ${PROJECT_BINARY_DIR}/doc/translator.py ${LANG_FILES}
OUTPUT language.doc
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc
)
set_source_files_properties(language.doc PROPERTIES GENERATED 1)
# doc/config.doc (see tag Doxyfile:INPUT)
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${TOP}/src/configgen.py -doc ${TOP}/src/config.xml > config.doc
DEPENDS ${TOP}/src/config.xml ${TOP}/src/configgen.py
OUTPUT config.doc
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
set_source_files_properties(config.doc PROPERTIES GENERATED 1)
################################################################################
add_custom_target(run_doxygen
COMMENT "Generating Latex and HTML documentation."
COMMAND ${CMAKE_COMMAND} -E env VERSION=${VERSION} ${DOXYGEN_EXECUTABLE}
DEPENDS ${PROJECT_BINARY_DIR}/doc/language.doc ${PROJECT_BINARY_DIR}/doc/config.doc
DEPENDS ${OUT_DOC_FILES}
DEPENDS examples
DEPENDS doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
add_custom_target(doxygen_pdf
COMMENT "Generating Doxygen Manual PDF."
COMMAND ${CMAKE_COMMAND} -E remove refman.tex
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex .
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc/manual.sty .
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/doxygen_logo.pdf .
COMMAND ${PDFLATEX} -cnf-line="openout_any=r" -shell-escape doxygen_manual.tex
COMMAND ${MAKEINDEX} doxygen_manual.idx
COMMAND ${PDFLATEX} -cnf-line="openout_any=r" -shell-escape doxygen_manual.tex
DEPENDS run_doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/latex
)
add_custom_target(docs
DEPENDS ${PROJECT_BINARY_DIR}/man/doxygen.1
${PROJECT_BINARY_DIR}/man/doxywizard.1
${PROJECT_BINARY_DIR}/man/doxysearch.1
${PROJECT_BINARY_DIR}/man/doxyindexer.1
doxygen_pdf
VERBATIM
)
# return status of ${HTML_HELP_COMPILER} is not correct, so we have to do a trick with an "or" statement
# output is redirected to "nul" as we are on windows no problem
if (build_doc_chm)
add_custom_target(docs_chm
COMMENT "Generating CHM documentation."
COMMAND ${CMAKE_COMMAND} -E env VERSION=${VERSION} HTML_HELP_COMPILER=${HTML_HELP_COMPILER} ${DOXYGEN_EXECUTABLE} Doxyfile_chm
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/html/examples ${PROJECT_BINARY_DIR}/chm/examples
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/chm/index.hhp ${PROJECT_BINARY_DIR}/chm/doxygen_manual.hhp
COMMAND ${CMAKE_COMMAND} -E echo "import os" > ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo "for root, dirs, files in os.walk('examples'):" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " for file in files:" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " if file.endswith('.html') or file.endswith('.png') or file.endswith('.css') or file.endswith('.gif'):" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " print(os.path.join(root, file))" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E chdir ${PROJECT_BINARY_DIR}/chm ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual.hhp
COMMAND ${CMAKE_COMMAND} -E chdir ${PROJECT_BINARY_DIR}/chm "${HTML_HELP_COMPILER}" doxygen_manual.hhp || echo > nul
COMMAND ${CMAKE_COMMAND} -E rename ${PROJECT_BINARY_DIR}/chm/index.chm ${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm
DEPENDS ${PROJECT_BINARY_DIR}/doc/language.doc ${PROJECT_BINARY_DIR}/doc/config.doc
DEPENDS ${OUT_DOC_FILES}
DEPENDS ${OUT_DOC_CHM_FILES}
DEPENDS examples
DEPENDS doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
endif ()
################################################################################
install(FILES
"${PROJECT_BINARY_DIR}/man/doxygen.1"
"${PROJECT_BINARY_DIR}/man/doxywizard.1"
"${PROJECT_BINARY_DIR}/man/doxysearch.1"
"${PROJECT_BINARY_DIR}/man/doxyindexer.1"
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
)
install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf\")
message(FATAL_ERROR \"\nTerminating:\n documentation has not been generated, \n create documentation by using the 'docs' target followed by an 'install'\n\")
endif()"
)
install(FILES
"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)
if (build_doc_chm)
install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm\")
message(FATAL_ERROR \"\nTerminating:\n CHM documentation has not been generated, \n create CHM documentation by using the 'docs_chm' target followed by an 'install'\n\")
endif()"
)
install(FILES
"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)
endif ()
install(DIRECTORY
"${PROJECT_BINARY_DIR}/html"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)

View File

@ -0,0 +1,25 @@
#
#
#
# Copyright (C) 1997-2015 by Dimitri van Heesch.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation under the terms of the GNU General Public License is hereby
# granted. No representations are made about the suitability of this software
# for any purpose. It is provided "as is" without express or implied warranty.
# See the GNU General Public License for more details.
#
# Documents produced by Doxygen are derivative works derived from the
# input used in their production; they are not affected by this license.
all: doxygen_manual.pdf
doxygen_manual.pdf: doxygen_manual.tex doxygen.sty
echo "Running latex..."
pdflatex -cnf-line="openout_any=r" doxygen_manual.tex
echo "Running makeindex..."
makeindex doxygen_manual.idx
echo "Rerunning latex...."
pdflatex -cnf-line="openout_any=r" doxygen_manual.tex
clean:
rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log doxygen_manual.pdf

View File

@ -0,0 +1,271 @@
# vim:ts=4:sw=4:expandtab:autoindent:
#
# Copyright (C) 1997-2015 by Dimitri van Heesch.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation under the terms of the GNU General Public License is hereby
# granted. No representations are made about the suitability of this software
# for any purpose. It is provided "as is" without express or implied warranty.
# See the GNU General Public License for more details.
#
# Documents produced by Doxygen are derivative works derived from the
# input used in their production; they are not affected by this license.
include (${TOP}/cmake/version.cmake)
string(TIMESTAMP DATE "%d-%m-%Y")
find_package(PythonInterp REQUIRED)
find_program(EPSTOPDF NAMES epstopdf )
find_program(PDFLATEX NAMES pdflatex )
find_program(MAKEINDEX NAMES makeindex )
include(GNUInstallDirs)
if (doxygen_BINARY_DIR)
set(DOXYGEN_EXECUTABLE ${doxygen_BINARY_DIR}/bin/doxygen)
else()
# when building only the doxygen_doc, from the doc/ directory, the
# doxygen project variables are unknown so look for doxygen in PATH
find_package(Doxygen)
endif()
set(DOC_INSTALL_DIR "share/doc/packages/doxygen" CACHE STRING "Relative path where to install the documentation")
set(DOC_FILES
arch.doc
archoverview.eps
archoverview.svg
autolink.doc
changelog.doc
commands.doc
custcmd.doc
customize.doc
diagrams.doc
docblocks.doc
Doxyfile
doxygen_manual.css
doxygen_usage.doc
doxywizard_expert.png
doxywizard_main.png
doxywizard_menu_file.png
doxywizard_menu_settings.png
doxywizard_menu_help.png
doxywizard_page1.png
doxywizard_page2.png
doxywizard_page3.png
doxywizard_page4.png
doxywizard_run.png
doxywizard_usage.doc
expert_bool.png
expert_enum.png
expert_int.png
expert_list_dir.png
expert_list_file.png
expert_list_filedir.png
expert_list_string.png
expert_string_dir.png
expert_string_file.png
expert_string_image.png
expert_string_string.png
external.doc
extsearch.doc
extsearch_flow.dot
extsearch_flow.eps
extsearch_flow.png
faq.doc
features.doc
formulas.doc
tables.doc
grouping.doc
htmlcmds.doc
index.doc
index.hhp.txt
infoflow.eps
infoflow.fig
infoflow.png
install.doc
install_prefix
lists.doc
markdown.doc
output.doc
perlmod.doc
perlmod_tree.doc
preprocessing.doc
searching.doc
starting.doc
trouble.doc
xmlcmds.doc
emojisup.doc
language.tpl
maintainers.txt
translator.py
smile.png
doxygen_logo.svg
)
set(DOC_FILES_IMAGES
add.png
del.png
file.png
folder.png
refresh.png
)
if (build_doc_chm)
set(DOC_FILES_CHM
Doxyfile_chm
)
endif ()
if (${CMAKE_VERSION} VERSION_EQUAL "3.11.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.11.0")
file(GLOB LANG_FILES CONFIGURE_DEPENDS "${TOP}/src//translator_??.h")
else()
file(GLOB LANG_FILES "${TOP}/src//translator_??.h")
endif()
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/man
${PROJECT_BINARY_DIR}/src
${PROJECT_BINARY_DIR}/doc
${PROJECT_BINARY_DIR}/doc/images)
foreach (f ${DOC_FILES})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/
DEPENDS ${PROJECT_SOURCE_DIR}/doc/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_FILES "${PROJECT_BINARY_DIR}/doc/${f}")
endforeach()
foreach (f ${DOC_FILES_IMAGES})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/images/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/addon/doxywizard/images/${f} ${PROJECT_BINARY_DIR}/doc/images/
DEPENDS ${PROJECT_SOURCE_DIR}/addon/doxywizard/images/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/images/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_FILES "${PROJECT_BINARY_DIR}/doc/images/${f}")
endforeach()
foreach (f ${DOC_FILES_CHM})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/
DEPENDS ${PROJECT_SOURCE_DIR}/doc/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_CHM_FILES "${PROJECT_BINARY_DIR}/doc/${f}")
endforeach()
configure_file(${PROJECT_SOURCE_DIR}/doc/manual.sty ${PROJECT_BINARY_DIR}/doc/manual.sty)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen_manual.tex ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen.1 ${PROJECT_BINARY_DIR}/man/doxygen.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxywizard.1 ${PROJECT_BINARY_DIR}/man/doxywizard.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxysearch.1 ${PROJECT_BINARY_DIR}/man/doxysearch.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxyindexer.1 ${PROJECT_BINARY_DIR}/man/doxyindexer.1)
# doc/language.doc (see tag Doxyfile:INPUT)
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} translator.py ${PROJECT_SOURCE_DIR}
DEPENDS ${PROJECT_SOURCE_DIR}/doc/maintainers.txt ${PROJECT_SOURCE_DIR}/doc/language.tpl ${PROJECT_BINARY_DIR}/doc/translator.py ${LANG_FILES}
OUTPUT language.doc
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc
)
set_source_files_properties(language.doc PROPERTIES GENERATED 1)
# doc/config.doc (see tag Doxyfile:INPUT)
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${TOP}/src/configgen.py -doc ${TOP}/src/config.xml > config.doc
DEPENDS ${TOP}/src/config.xml ${TOP}/src/configgen.py
OUTPUT config.doc
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
set_source_files_properties(config.doc PROPERTIES GENERATED 1)
################################################################################
add_custom_target(run_doxygen
COMMENT "Generating Latex and HTML documentation."
COMMAND ${CMAKE_COMMAND} -E env VERSION=${VERSION} ${DOXYGEN_EXECUTABLE}
DEPENDS ${PROJECT_BINARY_DIR}/doc/language.doc ${PROJECT_BINARY_DIR}/doc/config.doc
DEPENDS ${OUT_DOC_FILES}
DEPENDS examples
DEPENDS doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
add_custom_target(doxygen_pdf
COMMENT "Generating Doxygen Manual PDF."
COMMAND ${CMAKE_COMMAND} -E remove refman.tex
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex .
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc/manual.sty .
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/doxygen_logo.pdf .
COMMAND ${PDFLATEX} -shell-escape doxygen_manual.tex
COMMAND ${MAKEINDEX} doxygen_manual.idx
COMMAND ${PDFLATEX} -shell-escape doxygen_manual.tex
DEPENDS run_doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/latex
)
add_custom_target(docs
DEPENDS ${PROJECT_BINARY_DIR}/man/doxygen.1
${PROJECT_BINARY_DIR}/man/doxywizard.1
${PROJECT_BINARY_DIR}/man/doxysearch.1
${PROJECT_BINARY_DIR}/man/doxyindexer.1
doxygen_pdf
VERBATIM
)
# return status of ${HTML_HELP_COMPILER} is not correct, so we have to do a trick with an "or" statement
# output is redirected to "nul" as we are on windows no problem
if (build_doc_chm)
add_custom_target(docs_chm
COMMENT "Generating CHM documentation."
COMMAND ${CMAKE_COMMAND} -E env VERSION=${VERSION} HTML_HELP_COMPILER=${HTML_HELP_COMPILER} ${DOXYGEN_EXECUTABLE} Doxyfile_chm
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/html/examples ${PROJECT_BINARY_DIR}/chm/examples
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/chm/index.hhp ${PROJECT_BINARY_DIR}/chm/doxygen_manual.hhp
COMMAND ${CMAKE_COMMAND} -E echo "import os" > ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo "for root, dirs, files in os.walk('examples'):" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " for file in files:" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " if file.endswith('.html') or file.endswith('.png') or file.endswith('.css') or file.endswith('.gif'):" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " print(os.path.join(root, file))" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E chdir ${PROJECT_BINARY_DIR}/chm ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual.hhp
COMMAND ${CMAKE_COMMAND} -E chdir ${PROJECT_BINARY_DIR}/chm "${HTML_HELP_COMPILER}" doxygen_manual.hhp || echo > nul
COMMAND ${CMAKE_COMMAND} -E rename ${PROJECT_BINARY_DIR}/chm/index.chm ${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm
DEPENDS ${PROJECT_BINARY_DIR}/doc/language.doc ${PROJECT_BINARY_DIR}/doc/config.doc
DEPENDS ${OUT_DOC_FILES}
DEPENDS ${OUT_DOC_CHM_FILES}
DEPENDS examples
DEPENDS doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
endif ()
################################################################################
install(FILES
"${PROJECT_BINARY_DIR}/man/doxygen.1"
"${PROJECT_BINARY_DIR}/man/doxywizard.1"
"${PROJECT_BINARY_DIR}/man/doxysearch.1"
"${PROJECT_BINARY_DIR}/man/doxyindexer.1"
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
)
install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf\")
message(FATAL_ERROR \"\nTerminating:\n documentation has not been generated, \n create documentation by using the 'docs' target followed by an 'install'\n\")
endif()"
)
install(FILES
"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)
if (build_doc_chm)
install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm\")
message(FATAL_ERROR \"\nTerminating:\n CHM documentation has not been generated, \n create CHM documentation by using the 'docs_chm' target followed by an 'install'\n\")
endif()"
)
install(FILES
"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)
endif ()
install(DIRECTORY
"${PROJECT_BINARY_DIR}/html"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)

View File

@ -0,0 +1,25 @@
#
#
#
# Copyright (C) 1997-2015 by Dimitri van Heesch.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation under the terms of the GNU General Public License is hereby
# granted. No representations are made about the suitability of this software
# for any purpose. It is provided "as is" without express or implied warranty.
# See the GNU General Public License for more details.
#
# Documents produced by Doxygen are derivative works derived from the
# input used in their production; they are not affected by this license.
all: doxygen_manual.pdf
doxygen_manual.pdf: doxygen_manual.tex doxygen.sty
echo "Running latex..."
pdflatex doxygen_manual.tex
echo "Running makeindex..."
makeindex doxygen_manual.idx
echo "Rerunning latex...."
pdflatex doxygen_manual.tex
clean:
rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log doxygen_manual.pdf

View File

@ -0,0 +1,42 @@
find_package(Iconv)
include_directories(
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/libversion
${GENERATED_SRC}
${PROJECT_SOURCE_DIR}/qtools
${ICONV_INCLUDE_DIR}
${CLANG_INCLUDEDIR}
)
add_executable(doxyparse
doxyparse.cpp
)
add_sanitizers(doxyparse)
if (use_libclang)
if (static_libclang)
set(CLANG_LIBS libclang clangTooling ${llvm_libs})
else()
set(CLANG_LIBS libclang clang-cpp ${llvm_libs})
endif()
endif()
target_link_libraries(doxyparse
doxymain
qtools
md5
lodepng
mscgen
doxygen_version
doxycfg
vhdlparser
${ICONV_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${SQLITE3_LIBRARIES}
${EXTRA_LIBS}
${CLANG_LIBS}
${COVERAGE_LINKER_FLAGS}
)
install(TARGETS doxyparse DESTINATION bin)

View File

@ -0,0 +1,373 @@
# vim:ts=4:sw=4:expandtab:autoindent:
include_directories(
${PROJECT_SOURCE_DIR}/qtools
${PROJECT_SOURCE_DIR}/libmd5
${PROJECT_SOURCE_DIR}/liblodepng
${PROJECT_SOURCE_DIR}/libmscgen
${PROJECT_SOURCE_DIR}/libversion
${PROJECT_SOURCE_DIR}/vhdlparser
${PROJECT_SOURCE_DIR}/src
${CLANG_INCLUDEDIR}
${GENERATED_SRC}
)
file(MAKE_DIRECTORY ${GENERATED_SRC})
if (${CMAKE_VERSION} VERSION_EQUAL "3.11.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.11.0")
file(GLOB LANGUAGE_FILES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/translator_??.h")
else()
file(GLOB LANGUAGE_FILES "${CMAKE_CURRENT_LIST_DIR}/translator_??.h")
endif()
# instead of increasebuffer.py
add_definitions(-DYY_BUF_SIZE=${enlarge_lex_buffers} -DYY_READ_BUF_SIZE=${enlarge_lex_buffers})
# generate settings.h
file(GENERATE OUTPUT ${GENERATED_SRC}/settings.h
CONTENT "#ifndef SETTINGS_H
#define SETTINGS_H
#define USE_SQLITE3 ${sqlite3}
#define USE_LIBCLANG ${clang}
#define IS_SUPPORTED(x) \\
((USE_SQLITE3 && strcmp(\"USE_SQLITE3\",(x))==0) || \\
(USE_LIBCLANG && strcmp(\"USE_LIBCLANG\",(x))==0) || \\
0)
#endif" )
set_source_files_properties(${GENERATED_SRC}/settings.h PROPERTIES GENERATED 1)
# configvalues.h
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/configgen.py -maph ${CMAKE_CURRENT_LIST_DIR}/config.xml > ${GENERATED_SRC}/configvalues.h
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/config.xml ${CMAKE_CURRENT_LIST_DIR}/configgen.py
OUTPUT ${GENERATED_SRC}/configvalues.h
)
set_source_files_properties(${GENERATED_SRC}/configvalues.h PROPERTIES GENERATED 1)
add_custom_target(
generate_configvalues_header
DEPENDS ${GENERATED_SRC}/configvalues.h
)
# configvalues.cpp
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/configgen.py -maps ${CMAKE_CURRENT_LIST_DIR}/config.xml > ${GENERATED_SRC}/configvalues.cpp
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/config.xml ${CMAKE_CURRENT_LIST_DIR}/configgen.py
OUTPUT ${GENERATED_SRC}/configvalues.cpp
)
set_source_files_properties(${GENERATED_SRC}/configvalues.cpp PROPERTIES GENERATED 1)
# configoptions.cpp
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/configgen.py -cpp ${CMAKE_CURRENT_LIST_DIR}/config.xml > ${GENERATED_SRC}/configoptions.cpp
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/config.xml ${CMAKE_CURRENT_LIST_DIR}/configgen.py
OUTPUT ${GENERATED_SRC}/configoptions.cpp
)
set_source_files_properties(${GENERATED_SRC}/configoptions.cpp PROPERTIES GENERATED 1)
# ce_parse.h
add_custom_command(
COMMAND ${BISON_EXECUTABLE} -l -d -p ce_parsexpYY ${CMAKE_CURRENT_LIST_DIR}/constexp.y -o ce_parse.c
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/constexp.y
OUTPUT ${GENERATED_SRC}/ce_parse.h
WORKING_DIRECTORY ${GENERATED_SRC}
)
set_source_files_properties(${GENERATED_SRC}/ce_parse.h PROPERTIES GENERATED 1)
# lang_cfg.h
add_custom_command(
COMMENT "Generating ${GENERATED_SRC}/lang_cfg.h"
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/lang_cfg.cmake ${GENERATED_SRC}/lang_cfg.h ${LANG_CODES}
DEPENDS ${LANGUAGE_FILES}
OUTPUT ${GENERATED_SRC}/lang_cfg.h
)
set_source_files_properties(${GENERATED_SRC}/lang_cfg.h PROPERTIES GENERATED 1)
# all resource files
if (${CMAKE_VERSION} VERSION_EQUAL "3.11.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.11.0")
file(GLOB RESOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/templates/*/*)
else()
file(GLOB RESOURCES ${PROJECT_SOURCE_DIR}/templates/*/*)
endif()
# resources.cpp
add_custom_command(
COMMENT "Generating ${GENERATED_SRC}/resources.cpp"
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py ${PROJECT_SOURCE_DIR}/templates ${GENERATED_SRC}/resources.cpp
DEPENDS ${RESOURCES} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py
OUTPUT ${GENERATED_SRC}/resources.cpp
)
set_source_files_properties(${GENERATED_SRC}/resources.cpp PROPERTIES GENERATED 1)
set(LEX_FILES scanner
code
pyscanner
pycode
fortranscanner
fortrancode
vhdlcode
pre
declinfo
defargs
doctokenizer
commentcnv
commentscan
constexp
xml
xmlcode
sqlcode
configimpl)
# unfortunately ${LEX_FILES_H} and ${LEX_FILES_CPP} don't work in older versions of CMake (like 3.6.2) for add_library
foreach(lex_file ${LEX_FILES})
set(LEX_FILES_H ${LEX_FILES_H} " " ${GENERATED_SRC}/${lex_file}.l.h CACHE INTERNAL "Stores generated files")
set(LEX_FILES_CPP ${LEX_FILES_CPP} " " ${GENERATED_SRC}/${lex_file}.cpp CACHE INTERNAL "Stores generated files")
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/scan_states.py ${CMAKE_CURRENT_LIST_DIR}/${lex_file}.l > ${GENERATED_SRC}/${lex_file}.l.h
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/scan_states.py ${CMAKE_CURRENT_LIST_DIR}/${lex_file}.l
OUTPUT ${GENERATED_SRC}/${lex_file}.l.h
)
set_source_files_properties(${GENERATED_SRC}/${lex_file}.l.h PROPERTIES GENERATED 1)
# for code coverage we need the flex sources in the build src directory
add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/src/${lex_file}.l ${PROJECT_BINARY_DIR}/src/${lex_file}.l
DEPENDS ${PROJECT_SOURCE_DIR}/src/${lex_file}.l
OUTPUT ${PROJECT_BINARY_DIR}/src/${lex_file}.l
)
FLEX_TARGET(${lex_file}
${CMAKE_CURRENT_LIST_DIR}/${lex_file}.l
${GENERATED_SRC}/${lex_file}.cpp
COMPILE_FLAGS "${LEX_FLAGS}")
endforeach()
BISON_TARGET(constexp
${CMAKE_CURRENT_LIST_DIR}/constexp.y
${GENERATED_SRC}/ce_parse.cpp
COMPILE_FLAGS "${YACC_FLAGS}")
add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/src/constexp.y ${PROJECT_BINARY_DIR}/src
DEPENDS ${PROJECT_SOURCE_DIR}/src/constexp.y
OUTPUT ${PROJECT_BINARY_DIR}/src/constexp.y
)
add_library(doxycfg STATIC
${GENERATED_SRC}/lang_cfg.h
${GENERATED_SRC}/configvalues.h
${GENERATED_SRC}/configimpl.cpp
${GENERATED_SRC}/configimpl.l.h
${GENERATED_SRC}/configoptions.cpp
${GENERATED_SRC}/configvalues.cpp
${GENERATED_SRC}/settings.h
portable.cpp
portable_c.c
ftextstream.cpp
message.cpp
debug.cpp
)
add_sanitizers(doxycfg)
add_library(doxymain STATIC
# generated for/by flex/bison
#${LEX_FILES_H} #unfortunately doesn't work in older versions of CMake (like 3.6.2)
#${LEX_FILES_CPP} #unfortunately doesn't work in older versions of CMake (like 3.6.2)
${GENERATED_SRC}/code.l.h
${GENERATED_SRC}/commentcnv.l.h
${GENERATED_SRC}/commentscan.l.h
${GENERATED_SRC}/constexp.cpp
${GENERATED_SRC}/constexp.l.h
${GENERATED_SRC}/declinfo.l.h
${GENERATED_SRC}/defargs.l.h
${GENERATED_SRC}/doctokenizer.l.h
${GENERATED_SRC}/fortrancode.l.h
${GENERATED_SRC}/fortranscanner.l.h
${GENERATED_SRC}/pre.l.h
${GENERATED_SRC}/pycode.l.h
${GENERATED_SRC}/pyscanner.l.h
${GENERATED_SRC}/scanner.l.h
${GENERATED_SRC}/sqlcode.l.h
${GENERATED_SRC}/vhdlcode.l.h
${GENERATED_SRC}/xml.l.h
${GENERATED_SRC}/xmlcode.l.h
${GENERATED_SRC}/code.cpp
${GENERATED_SRC}/commentcnv.cpp
${GENERATED_SRC}/commentscan.cpp
${GENERATED_SRC}/declinfo.cpp
${GENERATED_SRC}/defargs.cpp
${GENERATED_SRC}/doctokenizer.cpp
${GENERATED_SRC}/fortrancode.cpp
${GENERATED_SRC}/fortranscanner.cpp
${GENERATED_SRC}/pre.cpp
${GENERATED_SRC}/pycode.cpp
${GENERATED_SRC}/pyscanner.cpp
${GENERATED_SRC}/scanner.cpp
${GENERATED_SRC}/sqlcode.cpp
${GENERATED_SRC}/vhdlcode.cpp
${GENERATED_SRC}/xml.cpp
${GENERATED_SRC}/xmlcode.cpp
#
${GENERATED_SRC}/ce_parse.cpp
# custom generated files
${GENERATED_SRC}/lang_cfg.h
${GENERATED_SRC}/ce_parse.h
${GENERATED_SRC}/resources.cpp
#
arguments.cpp
cite.cpp
clangparser.cpp
classdef.cpp
classlist.cpp
cmdmapper.cpp
condparser.cpp
context.cpp
cppvalue.cpp
defgen.cpp
definition.cpp
dia.cpp
diagram.cpp
dirdef.cpp
docbookgen.cpp
docbookvisitor.cpp
docgroup.cpp
docparser.cpp
docsets.cpp
docvisitor.cpp
dot.cpp
dotcallgraph.cpp
dotclassgraph.cpp
dotdirdeps.cpp
dotfilepatcher.cpp
dotgfxhierarchytable.cpp
dotgraph.cpp
dotgroupcollaboration.cpp
dotincldepgraph.cpp
dotlegendgraph.cpp
dotnode.cpp
dotrunner.cpp
doxygen.cpp
eclipsehelp.cpp
emoji.cpp
entry.cpp
filedef.cpp
fileparser.cpp
formula.cpp
ftvhelp.cpp
groupdef.cpp
htags.cpp
htmldocvisitor.cpp
htmlentity.cpp
htmlgen.cpp
htmlhelp.cpp
image.cpp
index.cpp
language.cpp
latexdocvisitor.cpp
latexgen.cpp
layout.cpp
mandocvisitor.cpp
mangen.cpp
markdown.cpp
memberdef.cpp
membergroup.cpp
memberlist.cpp
msc.cpp
namespacedef.cpp
outputgen.cpp
outputlist.cpp
pagedef.cpp
perlmodgen.cpp
plantuml.cpp
qhp.cpp
qhpxmlwriter.cpp
reflist.cpp
resourcemgr.cpp
rtfdocvisitor.cpp
rtfgen.cpp
rtfstyle.cpp
searchindex.cpp
sqlite3gen.cpp
stlsupport.cpp
symbolresolver.cpp
tagreader.cpp
template.cpp
textdocvisitor.cpp
tooltip.cpp
util.cpp
vhdldocgen.cpp
vhdljjparser.cpp
xmldocvisitor.cpp
xmlgen.cpp
)
add_sanitizers(doxymain)
# LLVM/clang headers give a lot of warnings with -Wshadow and -Wcast-align so we disable them for
# the one file that includes them
if (NOT MSVC)
set_source_files_properties(clangparser.cpp PROPERTIES COMPILE_FLAGS "-Wno-shadow -Wno-cast-align")
endif()
##foreach(lex_file ${LEX_FILES})
##add_library(doxymain STATIC ${GENERATED_SRC}/${lex_file}.l.h)
##endforeach()
add_executable(doxygen
main.cpp
)
add_sanitizers(doxygen)
if (use_libclang)
find_package(LLVM REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_features(doxymain PRIVATE cxx_alignof)
target_compile_features(doxygen PRIVATE cxx_alignof)
if (use_libc++)
target_compile_options(doxymain PRIVATE -stdlib=libc++)
target_compile_options(doxygen PRIVATE -stdlib=libc++)
endif()
endif()
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
if (static_libclang)
set(CLANG_LIBS libclang clangTooling)
else() # dynamically linked version of clang
llvm_config(doxymain USE_SHARED support)
set(CLANG_LIBS libclang clang-cpp)
endif()
target_compile_definitions(doxygen PRIVATE ${LLVM_DEFINITIONS})
endif()
target_link_libraries(doxygen PRIVATE
doxymain
doxycfg
qtools
md5
lodepng
mscgen
doxygen_version
vhdlparser
${SQLITE3_LIBRARIES}
${ICONV_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${EXTRA_LIBS}
${CLANG_LIBS}
${COVERAGE_LINKER_FLAGS}
${DOXYGEN_EXTRA_LINK_OPTIONS}
)
set_project_warnings(doxycfg)
set_project_warnings(doxymain)
set_project_warnings(doxygen)
set_project_coverage(qtools)
set_project_coverage(doxycfg)
set_project_coverage(doxymain)
set_project_coverage(doxygen)
install(TARGETS doxygen DESTINATION bin)

View File

@ -0,0 +1,62 @@
.TH DOXYGEN "1" "@DATE@" "doxygen @VERSION@" "User Commands"
.SH NAME
doxygen \- documentation system for various programming languages
.SH DESCRIPTION
Doxygen is a documentation system for C++, C, Java, Objective-C, IDL
(Corba and Microsoft flavors), Fortran, Python, VHDL and to some extent PHP, C#, and D.
.PP
You can use doxygen in a number of ways:
.TP
1) Use doxygen to generate a template configuration file:
.IP
doxygen [-s] \fB\-g\fR [configName]
.TP
2) Use doxygen to update an old configuration file:
.IP
doxygen [-s] \fB\-u\fR [configName]
.TP
3) Use doxygen to generate documentation using an existing configuration file:
.IP
doxygen [configName]
.TP
4) Use doxygen to generate a template file controlling the layout of the generated documentation:
.IP
doxygen -l [layoutFileName]
.IP
In case layoutFileName is omitted layoutFileName.xml will be used as filename.
If - is used for layoutFileName doxygen will write to standard output.
.TP
5) Use doxygen to generate a template style sheet file for RTF, HTML or Latex.
.IP
RTF:
doxygen \fB\-w\fR rtf styleSheetFile
.IP
HTML:
doxygen \fB\-w\fR html headerFile footerFile styleSheetFile [configFile]
.IP
LaTeX: doxygen \fB\-w\fR latex headerFile footerFile styleSheetFile [configFile]
.TP
6) Use doxygen to generate an rtf extensions file
.IP
RTF:
doxygen \fB\-e\fR rtf extensionsFile
.IP
If - is used for extensionsFile doxygen will write to standard output.
.TP
7) Use doxygen to compare the used configuration file with the template configuration file
.IP
doxygen \fB\-x\fR [configFile]
.TP
8) Use doxygen to show a list of built-in emojis.
.IP
doxygen \fB\-f\fR emoji outputFileName
.IP
If - is used for outputFileName doxygen will write to standard output.
.PP
If \fB\-s\fR is specified the comments in the config file will be omitted.
If configName is omitted `Doxyfile' will be used as a default.
If - is used for configFile doxygen will write / read the configuration to /from standard output / input.
.SH AUTHOR
Doxygen version @VERSION@, Copyright Dimitri van Heesch 1997-2019
.SH SEE ALSO
doxywizard(1).

View File

@ -0,0 +1,332 @@
# Doxyfile 1.8.16
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = Doxygen
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = doxygen_docs
CREATE_SUBDIRS = YES
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
JAVADOC_BANNER = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS =
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_PRIV_VIRTUAL = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# 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_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text "
WARN_LOGFILE = warnings.log
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = src \
vhdlparser
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.h \
*.cpp \
*.md
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT =
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = YES
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = YES
DOCSET_FEEDNAME = "Doxygen docs"
DOCSET_BUNDLE_ID = org.doxygen.Doxygen
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = YES
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH =
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = YES
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT =
LATEX_CMD_NAME =
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT =
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT =
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# 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 = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH = qtools \
libmd5 \
liblodepng \
libmscgen
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES = qtools_docs/qtools.tag=../../qtools_docs/html
GENERATE_TAGFILE = doxygen.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = svg
INTERACTIVE_SVG = YES
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 100
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = NO
DOT_MAX_FOLD = 17
DOT_UML_DETAILS = NO

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,271 @@
# vim:ts=4:sw=4:expandtab:autoindent:
#
# Copyright (C) 1997-2015 by Dimitri van Heesch.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation under the terms of the GNU General Public License is hereby
# granted. No representations are made about the suitability of this software
# for any purpose. It is provided "as is" without express or implied warranty.
# See the GNU General Public License for more details.
#
# Documents produced by Doxygen are derivative works derived from the
# input used in their production; they are not affected by this license.
include (${TOP}/cmake/version.cmake)
string(TIMESTAMP DATE "%d-%m-%Y")
find_package(PythonInterp REQUIRED)
find_program(EPSTOPDF NAMES epstopdf )
find_program(PDFLATEX NAMES pdflatex )
find_program(MAKEINDEX NAMES makeindex )
include(GNUInstallDirs)
if (doxygen_BINARY_DIR)
set(DOXYGEN_EXECUTABLE ${doxygen_BINARY_DIR}/bin/doxygen)
else()
# when building only the doxygen_doc, from the doc/ directory, the
# doxygen project variables are unknown so look for doxygen in PATH
find_package(Doxygen)
endif()
set(DOC_INSTALL_DIR "share/doc/packages/doxygen" CACHE STRING "Relative path where to install the documentation")
set(DOC_FILES
arch.doc
archoverview.eps
archoverview.svg
autolink.doc
changelog.doc
commands.doc
custcmd.doc
customize.doc
diagrams.doc
docblocks.doc
Doxyfile
doxygen_manual.css
doxygen_usage.doc
doxywizard_expert.png
doxywizard_main.png
doxywizard_menu_file.png
doxywizard_menu_settings.png
doxywizard_menu_help.png
doxywizard_page1.png
doxywizard_page2.png
doxywizard_page3.png
doxywizard_page4.png
doxywizard_run.png
doxywizard_usage.doc
expert_bool.png
expert_enum.png
expert_int.png
expert_list_dir.png
expert_list_file.png
expert_list_filedir.png
expert_list_string.png
expert_string_dir.png
expert_string_file.png
expert_string_image.png
expert_string_string.png
external.doc
extsearch.doc
extsearch_flow.dot
extsearch_flow.eps
extsearch_flow.png
faq.doc
features.doc
formulas.doc
tables.doc
grouping.doc
htmlcmds.doc
index.doc
index.hhp.txt
infoflow.eps
infoflow.fig
infoflow.png
install.doc
install_prefix
lists.doc
markdown.doc
output.doc
perlmod.doc
perlmod_tree.doc
preprocessing.doc
searching.doc
starting.doc
trouble.doc
xmlcmds.doc
emojisup.doc
language.tpl
maintainers.txt
translator.py
smile.png
doxygen_logo.svg
)
set(DOC_FILES_IMAGES
add.png
del.png
file.png
folder.png
refresh.png
)
if (build_doc_chm)
set(DOC_FILES_CHM
Doxyfile_chm
)
endif ()
if (${CMAKE_VERSION} VERSION_EQUAL "3.11.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.11.0")
file(GLOB LANG_FILES CONFIGURE_DEPENDS "${TOP}/src//translator_??.h")
else()
file(GLOB LANG_FILES "${TOP}/src//translator_??.h")
endif()
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/man
${PROJECT_BINARY_DIR}/src
${PROJECT_BINARY_DIR}/doc
${PROJECT_BINARY_DIR}/doc/images)
foreach (f ${DOC_FILES})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/
DEPENDS ${PROJECT_SOURCE_DIR}/doc/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_FILES "${PROJECT_BINARY_DIR}/doc/${f}")
endforeach()
foreach (f ${DOC_FILES_IMAGES})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/images/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/addon/doxywizard/images/${f} ${PROJECT_BINARY_DIR}/doc/images/
DEPENDS ${PROJECT_SOURCE_DIR}/addon/doxywizard/images/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/images/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_FILES "${PROJECT_BINARY_DIR}/doc/images/${f}")
endforeach()
foreach (f ${DOC_FILES_CHM})
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${f}
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/
DEPENDS ${PROJECT_SOURCE_DIR}/doc/${f}
)
set_source_files_properties(${PROJECT_BINARY_DIR}/doc/${f} PROPERTIES GENERATED 1)
list(APPEND OUT_DOC_CHM_FILES "${PROJECT_BINARY_DIR}/doc/${f}")
endforeach()
configure_file(${PROJECT_SOURCE_DIR}/doc/manual.sty ${PROJECT_BINARY_DIR}/doc/manual.sty)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen_manual.tex ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen.1 ${PROJECT_BINARY_DIR}/man/doxygen.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxywizard.1 ${PROJECT_BINARY_DIR}/man/doxywizard.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxysearch.1 ${PROJECT_BINARY_DIR}/man/doxysearch.1)
configure_file(${PROJECT_SOURCE_DIR}/doc/doxyindexer.1 ${PROJECT_BINARY_DIR}/man/doxyindexer.1)
# doc/language.doc (see tag Doxyfile:INPUT)
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} translator.py ${PROJECT_SOURCE_DIR}
DEPENDS ${PROJECT_SOURCE_DIR}/doc/maintainers.txt ${PROJECT_SOURCE_DIR}/doc/language.tpl ${PROJECT_BINARY_DIR}/doc/translator.py ${LANG_FILES}
OUTPUT language.doc
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc
)
set_source_files_properties(language.doc PROPERTIES GENERATED 1)
# doc/config.doc (see tag Doxyfile:INPUT)
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${TOP}/src/configgen.py -doc ${TOP}/src/config.xml > config.doc
DEPENDS ${TOP}/src/config.xml ${TOP}/src/configgen.py
OUTPUT config.doc
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
set_source_files_properties(config.doc PROPERTIES GENERATED 1)
################################################################################
add_custom_target(run_doxygen
COMMENT "Generating Latex and HTML documentation."
COMMAND ${CMAKE_COMMAND} -E env VERSION=${VERSION} ${DOXYGEN_EXECUTABLE}
DEPENDS ${PROJECT_BINARY_DIR}/doc/language.doc ${PROJECT_BINARY_DIR}/doc/config.doc
DEPENDS ${OUT_DOC_FILES}
DEPENDS examples
DEPENDS doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
add_custom_target(doxygen_pdf
COMMENT "Generating Doxygen Manual PDF."
COMMAND ${CMAKE_COMMAND} -E remove refman.tex
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex .
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc/manual.sty .
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/doxygen_logo.pdf .
COMMAND faketime @$ENV{SOURCE_DATE_EPOCH} ${PDFLATEX} -cnf-line="openout_any=r" -shell-escape doxygen_manual.tex
COMMAND ${MAKEINDEX} doxygen_manual.idx
COMMAND faketime @$ENV{SOURCE_DATE_EPOCH} ${PDFLATEX} -cnf-line="openout_any=r" -shell-escape doxygen_manual.tex
DEPENDS run_doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/latex
)
add_custom_target(docs
DEPENDS ${PROJECT_BINARY_DIR}/man/doxygen.1
${PROJECT_BINARY_DIR}/man/doxywizard.1
${PROJECT_BINARY_DIR}/man/doxysearch.1
${PROJECT_BINARY_DIR}/man/doxyindexer.1
doxygen_pdf
VERBATIM
)
# return status of ${HTML_HELP_COMPILER} is not correct, so we have to do a trick with an "or" statement
# output is redirected to "nul" as we are on windows no problem
if (build_doc_chm)
add_custom_target(docs_chm
COMMENT "Generating CHM documentation."
COMMAND ${CMAKE_COMMAND} -E env VERSION=${VERSION} HTML_HELP_COMPILER=${HTML_HELP_COMPILER} ${DOXYGEN_EXECUTABLE} Doxyfile_chm
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/html/examples ${PROJECT_BINARY_DIR}/chm/examples
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/chm/index.hhp ${PROJECT_BINARY_DIR}/chm/doxygen_manual.hhp
COMMAND ${CMAKE_COMMAND} -E echo "import os" > ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo "for root, dirs, files in os.walk('examples'):" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " for file in files:" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " if file.endswith('.html') or file.endswith('.png') or file.endswith('.css') or file.endswith('.gif'):" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E echo " print(os.path.join(root, file))" >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py
COMMAND ${CMAKE_COMMAND} -E chdir ${PROJECT_BINARY_DIR}/chm ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/chm/doxygen_manual_examples_chm.py >> ${PROJECT_BINARY_DIR}/chm/doxygen_manual.hhp
COMMAND ${CMAKE_COMMAND} -E chdir ${PROJECT_BINARY_DIR}/chm "${HTML_HELP_COMPILER}" doxygen_manual.hhp || echo > nul
COMMAND ${CMAKE_COMMAND} -E rename ${PROJECT_BINARY_DIR}/chm/index.chm ${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm
DEPENDS ${PROJECT_BINARY_DIR}/doc/language.doc ${PROJECT_BINARY_DIR}/doc/config.doc
DEPENDS ${OUT_DOC_FILES}
DEPENDS ${OUT_DOC_CHM_FILES}
DEPENDS examples
DEPENDS doxygen
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc/
)
endif ()
################################################################################
install(FILES
"${PROJECT_BINARY_DIR}/man/doxygen.1"
"${PROJECT_BINARY_DIR}/man/doxywizard.1"
"${PROJECT_BINARY_DIR}/man/doxysearch.1"
"${PROJECT_BINARY_DIR}/man/doxyindexer.1"
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
)
install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf\")
message(FATAL_ERROR \"\nTerminating:\n documentation has not been generated, \n create documentation by using the 'docs' target followed by an 'install'\n\")
endif()"
)
install(FILES
"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)
if (build_doc_chm)
install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm\")
message(FATAL_ERROR \"\nTerminating:\n CHM documentation has not been generated, \n create CHM documentation by using the 'docs_chm' target followed by an 'install'\n\")
endif()"
)
install(FILES
"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)
endif ()
install(DIRECTORY
"${PROJECT_BINARY_DIR}/html"
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}"
)

View File

@ -0,0 +1,592 @@
// This file is best viewed with Tab size 4 code indentation
// -----------------------------------------------------------------------------------------------------------------
// 1. Theme Quick Settings (Variables)
// (for further control, you will need to dig into the actual CSS in 2.)
// -----------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------
// :: 1.1. Colors
// ----------------------------------------------------------
$sm-dox__white: #fff !default;
$sm-dox__gray: darken($sm-dox__white, 6.5%) !default;
$sm-dox__gray-dark: darken($sm-dox__white, 26.5%) !default;
$sm-dox__gray-darker: darken($sm-dox__white, 66.5%) !default;
$sm-dox__red: #D23600 !default;
$sm-dox__box-shadow: rgba(0, 0, 0, 0.2) !default;
// ----------------------------------------------------------
// :: 1.2. Breakpoints
// ----------------------------------------------------------
$sm-dox__desktop-vp: 768px !default; // switch from collapsible to desktop
// ----------------------------------------------------------
// :: 1.3. Typography
// ----------------------------------------------------------
$sm-dox__font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif !default;
$sm-dox__font-size-base: 13px !default;
$sm-dox__font-size-small: 12px !default;
$sm-dox__line-height: 15px !default;
// ----------------------------------------------------------
// :: 1.4. Borders
// ----------------------------------------------------------
$sm-dox__border-width: 1px !default;
$sm-dox__border-radius: 5px !default;
// ----------------------------------------------------------
// :: 1.5. Collapsible main menu
// ----------------------------------------------------------
// Menu box
//$sm-dox__collapsible-bg: $sm-dox__gray !default;
$sm-dox__collapsible-bg: url('tab_b.png') !default;
$sm-dox__collapsible-border-radius: $sm-dox__border-radius !default;
// Items
$sm-dox__collapsible-item-color: $sm-dox__gray-darker !default;
$sm-dox__collapsible-item-current-color: $sm-dox__red !default;
$sm-dox__collapsible-item-disabled-color: darken($sm-dox__gray, 20%) !default;
$sm-dox__collapsible-item-padding-vertical: 0px !default;
$sm-dox__collapsible-item-padding-horizontal: 12px !default;
// Items separators
$sm-dox__collapsible-separators-color: rgba(0, 0, 0, 0.05) !default;
// Toggle button (sub menu indicators)
$sm-dox__collapsible-toggle-bg: rgba(255, 255, 255, 0.5) !default;
// ----------------------------------------------------------
// :: 1.6. Collapsible sub menus
// ----------------------------------------------------------
// Menu box
$sm-dox__collapsible-sub-bg: rgba(darken($sm-dox__gray, 30%), 0.1) !default;
// Items text indentation for deeper levels
$sm-dox__collapsible-sub-item-indentation: 8px !default;
// ----------------------------------------------------------
// :: 1.7. Desktop main menu
// ----------------------------------------------------------
// Menu box
//$sm-dox__desktop-bg: $sm-dox__gray !default;
$sm-dox__desktop-bg: url('tab_b.png') !default;
//$sm-dox__desktop-border-radius: 100px !default;
$sm-dox__desktop-padding-horizontal: 10px !default;
// Items
$sm-dox__desktop-item-color: $sm-dox__gray_darker !default;
$sm-dox__desktop-item-hover-color: $sm-dox__red !default;
$sm-dox__desktop-item-current-color: $sm-dox__red !default;
$sm-dox__desktop-item-disabled-color: darken($sm-dox__gray, 20%) !default;
$sm-dox__desktop-item-padding-vertical: 0px !default;
$sm-dox__desktop-item-padding-horizontal: 12px !default;
// Sub menu indicators
$sm-dox__desktop-arrow-size: 4px !default; // border-width
$sm-dox__desktop-arrow-color: $sm-dox__gray-darker !default;
$sm-dox__desktop-arrow-spacing: 4px !default;
// Vertical menu box
$sm-dox__desktop-vertical-border-radius: $sm-dox__border-radius !default;
$sm-dox__desktop-vertical-padding-vertical: 10px !default;
// Vertical items
$sm-dox__desktop-vertical-item-hover-bg: $sm-dox__white !default;
$sm-dox__desktop-vertical-item-padding-vertical: 10px !default;
$sm-dox__desktop-vertical-item-padding-horizontal: 20px !default;
$sm-dox__main-text-color: #283A5D !default;
$sm-dox__main-highlight-color: white !default;
// ----------------------------------------------------------
// :: 1.8. Desktop sub menus
// ----------------------------------------------------------
// Menu box
$sm-dox__desktop-sub-bg: $sm-dox__white !default;
$sm-dox__desktop-sub-border-color: $sm-dox__gray-dark !default;
$sm-dox__desktop-sub-border-radius: $sm-dox__border-radius !default;
$sm-dox__desktop-sub-box-shadow: 0 5px 9px $sm-dox__box-shadow !default;
$sm-dox__desktop-sub-padding-vertical: 5px !default;
$sm-dox__desktop-sub-padding-horizontal: 0 !default;
// Items
$sm-dox__desktop-sub-item-color: $sm-dox__gray_darker !default;
$sm-dox__desktop-sub-item-hover-color: $sm-dox__red !default;
$sm-dox__desktop-sub-item-hover-bg: $sm-dox__gray !default;
$sm-dox__desktop-sub-item-current-color: $sm-dox__red !default;
$sm-dox__desktop-sub-item-disabled-color: darken($sm-dox__white, 20%) !default;
$sm-dox__desktop-sub-item-padding-vertical: 10px !default;
$sm-dox__desktop-sub-item-padding-horizontal: 20px !default;
// Sub menu indicators
$sm-dox__desktop-sub-arrow-size: 5px !default; // border-width
// Sub menu carets
$sm-dox__desktop-sub-caret-size: 8px !default; // border-width
$sm-dox__desktop-sub-caret-left: 30px !default;
$sm-dox__main-row-height: 36px !default;
// -----------------------------------------------------------------------------------------------------------------
// 2. Theme CSS
// -----------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------
// :: 2.1. Collapsible mode (mobile first)
// ----------------------------------------------------------
// calc item height and sub menus toggle button size
$sm-dox__item-height: $sm-dox__line-height + $sm-dox__collapsible-item-padding-vertical * 2;
// set toggle button size to 80% of item height
$sm-dox__toggle-size: floor($sm-dox__main-row-height * 0.8);
$sm-dox__toggle-spacing: floor($sm-dox__main-row-height * 0.1);
// Main menu box
.sm-dox {
background-image: $sm-dox__collapsible-bg;
//border-radius: $sm-dox__collapsible-border-radius;
// Main menu items
a {
&,
&:focus,
&:hover,
&:active {
padding: $sm-dox__collapsible-item-padding-vertical $sm-dox__collapsible-item-padding-horizontal;
/* make room for the toggle button (sub indicator) */
padding-right: $sm-dox__collapsible-item-padding-horizontal + $sm-dox__toggle-size + $sm-dox__toggle-spacing;
/* color: $sm-dox__collapsible-item-color; */
font-family: $sm-dox__font-family;
font-size: $sm-dox__font-size-base;
font-weight: bold;
line-height: 36px; //$sm-dox__line-height;
text-decoration: none;
text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
color: $sm-dox__main-text-color;
outline: none;
}
&:hover {
background-image: url('tab_a.png');
background-repeat:repeat-x;
color: $sm-dox__main-highlight-color;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
}
&.current {
color: $sm-dox__collapsible-item-current-color;
}
&.disabled {
color: $sm-dox__collapsible-item-disabled-color;
}
// Toggle buttons (sub menu indicators)
span.sub-arrow {
position: absolute;
top: 50%;
margin-top: -(ceil($sm-dox__toggle-size / 2));
left: auto;
right: $sm-dox__toggle-spacing;
width: $sm-dox__toggle-size;
height: $sm-dox__toggle-size;
overflow: hidden;
font: bold #{$sm-dox__font-size-small}/#{$sm-dox__toggle-size} monospace !important;
text-align: center;
text-shadow: none;
background: $sm-dox__collapsible-toggle-bg;
border-radius: $sm-dox__border-radius;
}
// Change + to - on sub menu expand
&.highlighted span.sub-arrow:before {
display: block;
content: '-';
}
}
// round the corners of the first item
> li:first-child > a, > li:first-child > :not(ul) a {
border-radius: $sm-dox__collapsible-border-radius $sm-dox__collapsible-border-radius 0 0;
}
// round the corners of the last item
@include sm-dox__round-corners-last-item($sm-dox__collapsible-border-radius);
// Main menu items separators
//li {
// /*border-top: 1px solid $sm-dox__collapsible-separators-color;*/
// border-top: 0;
//}
//> li:first-child {
// border-top: 0;
//}
// Sub menus box
ul {
background: $sm-dox__collapsible-sub-bg;
// Sub menus items
a {
&,
&:focus,
&:hover,
&:active {
font-size: $sm-dox__font-size-small;
// add indentation for sub menus text
border-left: $sm-dox__collapsible-sub-item-indentation solid transparent;
//line-height: $sm-dox__line-height;
line-height: $sm-dox__main-row-height;
text-shadow: none;
background-color: white;
background-image: none;
}
&:hover {
// color: $sm-dox__collapsible-item-current-color;
// background-color: $sm-dox__gray;
background-image: url('tab_a.png');
background-repeat:repeat-x;
color: $sm-dox__main-highlight-color;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
}
}
// Add indentation for sub menus text for deeper levels
@include sm-dox__sub-items-indentation($sm-dox__collapsible-sub-item-indentation);
}
}
// ----------------------------------------------------------
// :: 2.2. Desktop mode
// ----------------------------------------------------------
@media (min-width: $sm-dox__desktop-vp) {
/* Switch to desktop layout
-----------------------------------------------
These transform the menu tree from
collapsible to desktop (navbar + dropdowns)
-----------------------------------------------*/
/* start... (it's not recommended editing these rules) */
.sm-dox ul{position:absolute;width:12em;}
.sm-dox li{float:left;}
.sm-dox.sm-rtl li{float:right;}
.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none;}
.sm-dox a{white-space:nowrap;}
.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal;}
.sm-dox .sm-nowrap > li > a,.sm-dox .sm-nowrap > li > :not(ul) a{white-space:nowrap;}
/* ...end */
// Main menu box
.sm-dox {
padding: 0 $sm-dox__desktop-padding-horizontal;
background-image: $sm-dox__desktop-bg;
line-height: 36px;
//border-radius: $sm-dox__desktop-border-radius;
// Main menu items
a {
// Sub menu indicators
span.sub-arrow {
top: 50%;
margin-top: -(ceil($sm-dox__desktop-arrow-size / 2));
right: $sm-dox__desktop-item-padding-horizontal;
width: 0;
height: 0;
border-width: $sm-dox__desktop-arrow-size;
border-style: solid dashed dashed dashed;
border-color: $sm-dox__main-text-color transparent transparent transparent;
background: transparent;
border-radius: 0;
}
&,
&:focus,
&:active,
&:hover,
&.highlighted {
padding: $sm-dox__desktop-item-padding-vertical $sm-dox__desktop-item-padding-horizontal;
/*color: $sm-dox__desktop-item-color;*/
background-image:url('tab_s.png');
background-repeat:no-repeat;
background-position:right;
border-radius: 0 !important;
}
&:hover {
background-image: url('tab_a.png');
background-repeat:repeat-x;
color: $sm-dox__main-highlight-color;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
span.sub-arrow {
border-color: $sm-dox__main-highlight-color transparent transparent transparent;
}
}
// Make room for the sub arrows
&.has-submenu {
padding-right: $sm-dox__desktop-item-padding-horizontal + $sm-dox__desktop-arrow-size * 2 + $sm-dox__desktop-arrow-spacing;
}
}
// No main menu items separators
li {
border-top: 0;
}
// First sub level carets
> li > ul:before,
> li > ul:after {
content: '';
position: absolute;
top: -($sm-dox__desktop-sub-caret-size * 2 + $sm-dox__border-width * 2);
left: $sm-dox__desktop-sub-caret-left;
width: 0;
height: 0;
overflow: hidden;
border-width: ($sm-dox__desktop-sub-caret-size + $sm-dox__border-width);
border-style: dashed dashed solid dashed;
border-color: transparent transparent $sm-dox__gray-dark transparent;
}
> li > ul:after {
top: -($sm-dox__desktop-sub-caret-size * 2);
left: ($sm-dox__desktop-sub-caret-left + $sm-dox__border-width);
border-width: $sm-dox__desktop-sub-caret-size;
border-color: transparent transparent $sm-dox__desktop-sub-bg transparent;
}
// Sub menus box
ul {
border: $sm-dox__border-width solid $sm-dox__gray-dark;
padding: $sm-dox__desktop-sub-padding-vertical $sm-dox__desktop-sub-padding-horizontal;
background: $sm-dox__desktop-sub-bg;
border-radius: $sm-dox__desktop-sub-border-radius !important;
box-shadow: $sm-dox__desktop-sub-box-shadow;
// Sub menus items
a {
span.sub-arrow {
right: 8px;
top: 50%;
margin-top: -$sm-dox__desktop-sub-arrow-size;
border-width: $sm-dox__desktop-sub-arrow-size;
border-color: transparent transparent transparent $sm-dox__desktop-sub-item-color;
border-style: dashed dashed dashed solid;
}
&,
&:hover,
&:focus,
&:active,
&.highlighted {
color: $sm-dox__desktop-sub-item-color;
background-image:none;
border: 0 !important;
color: $sm-dox__desktop-sub-item-color;
background-image:none;
}
&:hover {
background-image: url('tab_a.png');
background-repeat:repeat-x;
color: $sm-dox__main-highlight-color;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
span.sub-arrow {
border-color: transparent transparent transparent $sm-dox__main-highlight-color;
}
}
}
}
// Scrolling arrows containers for tall sub menus - test sub menu: "Sub test" -> "more..." in the default download package
span.scroll-up,
span.scroll-down {
position: absolute;
display: none;
visibility: hidden;
overflow: hidden;
background: $sm-dox__desktop-sub-bg;
height: 36px;
// width and position will be set automatically by the script
&:hover {
background: $sm-dox__desktop-sub-item-hover-bg;
}
}
span.scroll-up:hover span.scroll-up-arrow {
border-color: transparent transparent $sm-dox__desktop-sub-item-hover-color transparent;
}
span.scroll-down:hover span.scroll-down-arrow {
border-color: $sm-dox__desktop-sub-item-hover-color transparent transparent transparent;
}
span.scroll-up-arrow {
position: absolute;
top: 0;
left: 50%;
margin-left: -6px;
// we will use one-side border to create a triangle so that we don't use a real background image, of course, you can use a real image if you like too
width: 0;
height: 0;
overflow: hidden;
border-width: 6px; // tweak size of the arrow
border-style: dashed dashed solid dashed;
border-color: transparent transparent $sm-dox__desktop-sub-item-color transparent;
}
span.scroll-down-arrow {
@extend span.scroll-up-arrow;
top: 8px;
border-style: solid dashed dashed dashed;
border-color: $sm-dox__desktop-sub-item-color transparent transparent transparent;
}
// Rigth-to-left
// Main menu box
&.sm-rtl {
// Main menu items
a {
// Make room for the sub arrows
&.has-submenu {
padding-right: $sm-dox__desktop-item-padding-horizontal;
padding-left: $sm-dox__desktop-item-padding-horizontal + $sm-dox__desktop-arrow-size * 2 + $sm-dox__desktop-arrow-spacing;
}
// Sub menu indicators
span.sub-arrow {
right: auto;
left: $sm-dox__desktop-item-padding-horizontal;
}
}
// Vertical main menu items
&.sm-vertical {
a {
// No need for additional room for the sub arrows
&.has-submenu {
padding: $sm-dox__desktop-vertical-item-padding-vertical $sm-dox__desktop-vertical-item-padding-horizontal;
}
// Sub menu indicators
span.sub-arrow {
right: auto;
left: 8px;
border-style: dashed solid dashed dashed;
border-color: transparent $sm-dox__desktop-arrow-color transparent transparent;
}
}
}
// First sub level carets
> li > ul:before {
left: auto;
right: $sm-dox__desktop-sub-caret-left;
}
> li > ul:after {
left: auto;
right: ($sm-dox__desktop-sub-caret-left + $sm-dox__border-width);
}
// Sub menus box
ul {
a {
// No need for additional room for the sub arrows
&.has-submenu {
padding: $sm-dox__desktop-sub-item-padding-vertical $sm-dox__desktop-sub-item-padding-horizontal !important;
}
// Sub menu indicators
span.sub-arrow {
right: auto;
left: 8px;
border-style: dashed solid dashed dashed;
border-color: transparent $sm-dox__desktop-arrow-color transparent transparent;
}
}
}
}
// Vertical main menu
// Main menu box
&.sm-vertical {
padding: $sm-dox__desktop-vertical-padding-vertical 0;
border-radius: $sm-dox__desktop-vertical-border-radius;
// Main menu items
a {
padding: $sm-dox__desktop-vertical-item-padding-vertical $sm-dox__desktop-vertical-item-padding-horizontal;
&:hover,
&:focus,
&:active,
&.highlighted {
background: $sm-dox__desktop-vertical-item-hover-bg;
}
&.disabled {
background-image: $sm-dox__desktop-bg;
}
// Sub menu indicators
span.sub-arrow {
right: 8px;
top: 50%;
margin-top: -$sm-dox__desktop-sub-arrow-size;
border-width: $sm-dox__desktop-sub-arrow-size;
border-style: dashed dashed dashed solid;
border-color: transparent transparent transparent $sm-dox__desktop-arrow-color;
}
}
// No sub level carets
> li > ul:before,
> li > ul:after {
display: none;
}
// Sub menus box
ul {
// Sub menus items
a {
padding: $sm-dox__desktop-sub-item-padding-vertical $sm-dox__desktop-sub-item-padding-horizontal;
&:hover,
&:focus,
&:active,
&.highlighted {
background: $sm-dox__desktop-sub-item-hover-bg;
}
&.disabled {
background: $sm-dox__desktop-sub-bg;
}
}
}
}
}
}

55
BUILD.txt Normal file
View File

@ -0,0 +1,55 @@
Doxygen uses cmake (http://www.cmake.org/) to build executables for various platforms.
It's required at least cmake version 3.3.
The first step is to create a build directory where the output should be stored.
Doxygen can be fully build outside of the source tree.
The second step is to invoke cmake from within the build directory with the desired generator.
For Linux/Unix systems do the following
mkdir build
cd build
cmake -G "Unix Makefiles" path/to/root/of/doxygen/source/tree
make
This also works for MacOSX, but if XCode is installed you can also generate an XCode project file
cmake -G XCode path/to/root/of/doxygen/source/tree
For Windows one can generate a Visual Studio project using
cmake -G "Visual Studio 12 2013" path\to\root\of\doxygen\source\tree
(this is for Visual Studio 12, there are typically also generators for other versions of
Visual Studio or other compiler environments like MinGW)
Doxygen's cmake configuration provides a number of options:
- build_wizard Build the GUI frontend for doxygen.
- build_app Example showing how to embed doxygen in an application.
- build_parse Parses source code and dumps the dependencies between the code elements.
- build_xmlparser Example showing how to parse doxygen's XML output.
- build_search Build external search tools (doxysearch and doxyindexer).
- build_doc Build user manual.
- use_sqlite3 Add support for sqlite3 output [experimental].
- use_libclang Add support for libclang parsing.
- win_static Link with /MT in stead of /MD on windows.
- english_only Only compile in support for the English language.
- force_qt4 Forces doxywizard to build using Qt4 even if Qt5 is installed
An option can be turned on, by adding -D<option>=ON as a command line option, this can be
done when generating the initial build files, but also afterwards, i.e. to enable building
of the documentation after an initial cmake -G run, do
cmake -Dbuild_doc=ON path/to/root/of/doxygen/source/tree
To turn the option off use
cmake -Dbuild_doc=OFF path/to/root/of/doxygen/source/tree
To see the current value is of the various options, you can run
cmake -L path/to/root/of/doxygen/source/tree
The build target for building the documentation is 'docs' and the build target for
the regression tests is 'tests'

201
CMakeLists.txt Normal file
View File

@ -0,0 +1,201 @@
# vim:ts=4:sw=4:expandtab:autoindent:
#
# Copyright (C) 1997-2015 by Dimitri van Heesch.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation under the terms of the GNU General Public License is hereby
# granted. No representations are made about the suitability of this software
# for any purpose. It is provided "as is" without express or implied warranty.
# See the GNU General Public License for more details.
#
# Documents produced by Doxygen are derivative works derived from the
# input used in their production; they are not affected by this license.
cmake_minimum_required(VERSION 3.3)
project(doxygen)
option(build_wizard "Build the GUI frontend for doxygen." OFF)
option(build_app "Example showing how to embed doxygen in an application." OFF)
option(build_parse "Parses source code and dumps the dependencies between the code elements." OFF)
option(build_xmlparser "Example showing how to parse doxygen's XML output." OFF)
option(build_search "Build external search tools (doxysearch and doxyindexer)" OFF)
option(build_doc "Build user manual (HTML and PDF)" OFF)
option(build_doc_chm "Build user manual (CHM)" OFF)
option(use_sqlite3 "Add support for sqlite3 output [experimental]." OFF)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
option(use_libc++ "Use libc++ as C++ standard library." ON)
endif()
option(use_libclang "Add support for libclang parsing." OFF)
option(static_libclang "Link to a statically compiled version of LLVM/libclang." OFF)
option(win_static "Link with /MT in stead of /MD on windows" OFF)
option(english_only "Only compile in support for the English language" OFF)
option(force_qt4 "Forces doxywizard to build using Qt4 even if Qt5 is installed" OFF)
option(enable_coverage "Enable coverage reporting for gcc/clang [development]" OFF)
SET(enlarge_lex_buffers "262144" CACHE INTERNAL "Sets the lex input and read buffers to the specified size")
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Sanitizers")
set(TOP "${PROJECT_SOURCE_DIR}")
include(version)
set(sqlite3 "0" CACHE INTERNAL "used in settings.h")
set(clang "0" CACHE INTERNAL "used in settings.h")
if (use_sqlite3)
set(sqlite3 "1" CACHE INTERNAL "used in settings.h")
endif()
set(MACOS_VERSION_MIN 10.9)
if (use_libclang)
set(clang "1" CACHE INTERNAL "used in settings.h")
find_package(LLVM CONFIG REQUIRED)
find_package(Clang CONFIG REQUIRED)
if (CMAKE_SYSTEM MATCHES "Darwin")
set(MACOS_VERSION_MIN 10.14)
endif()
endif()
# use C++14 standard for compiling (libclang option requires it)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)
if (CMAKE_SYSTEM MATCHES "Darwin")
set(CMAKE_CXX_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_CXX_FLAGS}")
set(CMAKE_C_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_C_FLAGS}")
find_library(CORESERVICES_LIB CoreServices)
set(EXTRA_LIBS ${CORESERVICES_LIB})
endif()
if (WIN32)
if ((NOT CMAKE_GENERATOR MATCHES "MinGW Makefiles") AND
(NOT CMAKE_GENERATOR MATCHES "MSYS Makefiles") AND
(NOT CMAKE_GENERATOR MATCHES "Unix Makefiles"))
if (NOT ICONV_DIR)
set(ICONV_DIR "${PROJECT_SOURCE_DIR}/winbuild")
endif()
set(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") # needed for language.cpp on 64bit
add_definitions(-DLIBICONV_STATIC -D_CRT_SECURE_NO_WARNINGS)
endif()
if (CMAKE_GENERATOR MATCHES "NMake Makefiles")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
endif()
endif()
if(POLICY CMP0063)
cmake_policy(SET CMP0063 NEW)
endif()
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
if (CMAKE_GENERATOR MATCHES "Ninja")
set(LEX_FLAGS )
set(YACC_FLAGS )
set(JAVACC_FLAGS )
else ()
set(LEX_FLAGS $(LEX_FLAGS))
set(YACC_FLAGS $(YACC_FLAGS))
set(JAVACC_FLAGS $(JAVACC_FLAGS))
endif ()
find_program(DOT NAMES dot)
find_package(PythonInterp REQUIRED)
find_package(FLEX REQUIRED)
find_package(BISON REQUIRED)
if (BISON_VERSION VERSION_LESS 2.7)
message(SEND_ERROR "Doxygen requires at least bison version 2.7 (installed: ${BISON_VERSION})")
endif()
find_package(Threads)
find_package(Sanitizers)
if (sqlite3)
find_package(SQLite3 REQUIRED)
if (SQLITE3_VERSION VERSION_LESS 3.9.0)
message(SEND_ERROR "Doxygen requires at least sqlite3 version 3.9.0 (installed: ${SQLITE3_VERSION})")
endif()
endif()
find_package(Iconv REQUIRED)
include_directories(${ICONV_INCLUDE_DIR})
#set(DOXYDOCS ${PROJECT_SOURCE_DIR}/doc CACHE INTERNAL "Path to doxygen docs")
set(DOXYDOCS ${PROJECT_BINARY_DIR}/doc)
set(ENV{DOXYGEN_DOCDIR} ${DOXYDOCS})
set(GENERATED_SRC "${PROJECT_BINARY_DIR}/generated_src" CACHE INTERNAL "Stores generated files")
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# place binaries for all build types in the same directory, so we know where to find it
# when running tests or generating docs
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${EXECUTABLE_OUTPUT_PATH})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${EXECUTABLE_OUTPUT_PATH})
# gather lang codes for translation
file(GLOB lang_files RELATIVE "${PROJECT_SOURCE_DIR}/src" "${PROJECT_SOURCE_DIR}/src/translator_??.h")
if (english_only) # user only wants English
set(lcodes "ENONLY")
else ()
set(lcodes "")
foreach (_lang ${lang_files})
string(REGEX REPLACE "translator_(.*).h" "\\1" _lang_code ${_lang})
string(TOUPPER ${_lang_code} lang_code)
list(APPEND lcodes "${lang_code}")
endforeach()
endif()
set(LANG_CODES ${lcodes} CACHE STRING "List of language codes for which translations should be compiled in")
if (win_static)
set(CompilerFlags
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO)
foreach(CompilerFlag ${CompilerFlags})
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
endforeach()
endif()
include(cmake/CompilerWarnings.cmake)
include(cmake/Coverage.cmake)
add_subdirectory(libmd5)
add_subdirectory(liblodepng)
add_subdirectory(libmscgen)
add_subdirectory(libversion)
add_subdirectory(qtools)
add_subdirectory(vhdlparser)
add_subdirectory(src)
if (build_doc_chm)
if (WIN32)
find_package(HTMLHelp REQUIRED)
set(build_doc ON)
else ()
message(WARNING "CHM documentation generation not supported for this platform, ignoring setting.")
set(build_doc_chm OFF)
endif ()
endif ()
if (build_doc)
add_subdirectory(examples)
add_subdirectory(doc)
endif ()
add_subdirectory(addon)
enable_testing()
add_subdirectory(testing)
include(cmake/packaging.cmake) # set CPACK_xxxx properties
include(CPack)

332
Doxyfile Normal file
View File

@ -0,0 +1,332 @@
# Doxyfile 1.8.16
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = Doxygen
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = doxygen_docs
CREATE_SUBDIRS = YES
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
JAVADOC_BANNER = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS =
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_PRIV_VIRTUAL = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# 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_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text "
WARN_LOGFILE = warnings.log
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = src \
vhdlparser
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.h \
*.cpp \
*.md
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT =
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = YES
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = YES
DOCSET_FEEDNAME = "Doxygen docs"
DOCSET_BUNDLE_ID = org.doxygen.Doxygen
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = YES
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH =
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = YES
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT =
LATEX_CMD_NAME =
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT =
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT =
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# 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 = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH = qtools \
libmd5 \
liblodepng \
libmscgen
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES = qtools_docs/qtools.tag=../../qtools_docs/html
GENERATE_TAGFILE = doxygen.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = svg
INTERACTIVE_SVG = YES
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 100
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = NO
DOT_MAX_FOLD = 17
DOT_UML_DETAILS = NO

7
INSTALL Normal file
View File

@ -0,0 +1,7 @@
DOXYGEN
Please read the installation section of the manual
(https://www.doxygen.nl/manual/install.html) for instructions.
--------
Dimitri van Heesch

50
LANGUAGE.HOWTO Normal file
View File

@ -0,0 +1,50 @@
This short howto explains how to add support for a new language to Doxygen:
Just follow these steps:
1) Tell me which language you want to add support for. If no one else
is already working on support for that language, you will be
assigned as the maintainer for the language. I'll create a
list on Doxygen's homepage, so everyone knows who is doing what.
2) Create a copy of translator_en.h and name it
translator_<your_2_letter_country_code>.h
I'll use xx in the rest of this document.
3) Edit language.cpp:
- Add a #include<translator_xx.h>
- In setTranslator() add
else if (L_EQUAL("your_language_name"))
{
theTranslator = new TranslatorYourLanguage;
}
after the if { ... }
4) Edit libdoxygen.pro.in and add translator_xx.h to the HEADERS line.
5) Edit translator_xx.h:
- Change TRANSLATOR_EN_H to TRANSLATOR_XX_H (in both the #include line and
the #define line).
- Change TranslatorEnglish to TranslatorYourLanguage
- In the member idLanguage() change "english" into the name of your
language (use lower case characters only). Depending on the language you
may also wish to change the member functions latexLanguageSupportCommand()
and idLanguageCharset().
- Edit all the strings that are returned by the members that start
with tr. Try to match punctuation and capitals!
To enter special characters (with accents) you can:
a) Enter them directly if your keyboard supports that and you are
using a Latin-1 font.
Doxygen will translate the characters to proper Latex and
leave the Html and man output for what it is (which is fine, if
idLanguageCharset() is set correctly).
b) Use html codes like &auml; for an a with an umlaut (i.e. ä).
See the HTML specification for the codes.
6) Run configure and make again from the root of the distribution,
in order to regenerate the Makefiles.
7) Now you can use OUTPUT_LANGUAGE = your_language_name
in the config file to generate output in your language.
8) Send translator_xx.h to me so I can add it to doxygen.
Send also your name and e-mail address to be included in the
maintainers.txt list.
Good luck, and let me know if there are problems.

339
LICENSE Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

68
README.md Normal file
View File

@ -0,0 +1,68 @@
Doxygen
===============
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9HHLRBCC8B2B8)
Doxygen is the de facto standard tool for generating documentation from
annotated C++ sources, but it also supports other popular programming
languages such as C, Objective-C, C#, PHP, Java, Python, IDL
(Corba, Microsoft, and UNO/OpenOffice flavors), Fortran, VHDL,
and to some extent D.
Doxygen can help you in three ways:
1. It can generate an on-line documentation browser (in HTML) and/or an
off-line reference manual (in LaTeX) from a set of documented source files.
There is also support for generating output in RTF (MS-Word), PostScript,
hyperlinked PDF, compressed HTML, DocBook and Unix man pages.
The documentation is extracted directly from the sources, which makes
it much easier to keep the documentation consistent with the source code.
2. You can configure doxygen to extract the code structure from undocumented
source files. This is very useful to quickly find your way in large
source distributions. Doxygen can also visualize the relations between
the various elements by means of include dependency graphs, inheritance
diagrams, and collaboration diagrams, which are all generated automatically.
3. You can also use doxygen for creating normal documentation (as I did for
the doxygen user manual and doxygen web-site).
Download
---------
The latest binaries and source of Doxygen can be downloaded from:
* https://www.doxygen.nl/
Developers
---------
* Linux & Windows and MacOS Build Status: <a href="https://github.com/doxygen/doxygen/actions"><img alt="Github Actions Build Status" src="https://github.com/doxygen/doxygen/workflows/CMake%20Build%20for%20Doxygen/badge.svg"></a>
* Coverity Scan Build Status: <a href="https://scan.coverity.com/projects/2860"> <img alt="Coverity Scan Build Status" src="https://scan.coverity.com/projects/2860/badge.svg"/> </a>
* Doxygen's Doxygen Documentation: <a href="https://codedocs.xyz/doxygen/doxygen/"><img src="https://codedocs.xyz/doxygen/doxygen.svg"/></a>
* Install: Please read the installation section of the manual (https://www.doxygen.nl/manual/install.html)
* Project stats: https://www.openhub.net/p/doxygen
Issues, bugs, requests, ideas
----------------------------------
Use the [issue](https://github.com/doxygen/doxygen/issues) tracker to report bugs.
Comms
----------------------------------
### Mailing Lists ###
There are three mailing lists:
* doxygen-announce@lists.sourceforge.net - Announcement of new releases only
* doxygen-users@lists.sourceforge.net - for doxygen users
* doxygen-develop@lists.sourceforge.net - for doxygen developers
* To subscribe follow the link to
* https://sourceforge.net/projects/doxygen/
Source Code
----------------------------------
In May 2013, Doxygen moved from
subversion to git hosted at GitHub
* https://github.com/doxygen/doxygen
Enjoy,
Dimitri van Heesch (doxygen at gmail.com)

1
VERSION Normal file
View File

@ -0,0 +1 @@
1.9.1

19
addon/CMakeLists.txt Normal file
View File

@ -0,0 +1,19 @@
if (build_xmlparser)
add_subdirectory(doxmlparser)
endif ()
if (build_app)
add_subdirectory(doxyapp)
endif ()
if (build_parse)
add_subdirectory(doxyparse)
endif ()
if (build_search)
add_subdirectory(doxysearch)
endif ()
if (build_wizard)
add_subdirectory(doxywizard)
endif ()

View File

@ -0,0 +1,4 @@
add_subdirectory(src)
add_subdirectory(examples)
add_subdirectory(test)

334
addon/doxmlparser/Doxyfile Normal file
View File

@ -0,0 +1,334 @@
# Doxyfile 1.8.17
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = doxmlparser
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = doc
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
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
JAVADOC_BANNER = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 5
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_PRIV_VIRTUAL = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
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
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# 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_AS_ERROR = NO
WARN_FORMAT =
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = include
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.h
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
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_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = NO
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT =
LATEX_CMD_NAME =
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT =
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT =
MAN_EXTENSION =
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = YES
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# 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 options related to external references
#---------------------------------------------------------------------------
TAGFILES = ../../qtools_docs/qtools.tag=../../../../qtools_docs/html
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

View File

@ -0,0 +1,334 @@
# Doxyfile 1.8.17
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = doxmlparser
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = doc_impl
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
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
JAVADOC_BANNER = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 5
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_PRIV_VIRTUAL = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
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
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# 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_AS_ERROR = NO
WARN_FORMAT =
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = src
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
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_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = NO
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT =
LATEX_CMD_NAME =
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT =
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT =
MAN_EXTENSION =
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = YES
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# 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 = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED = DEFINE_CLS_IMPL
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES = ../../qtools_docs/qtools.tag=../../../../qtools_docs/html
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

View File

@ -0,0 +1,2 @@
add_subdirectory(metrics)

View File

@ -0,0 +1,18 @@
include_directories(
../../include
${PROJECT_SOURCE_DIR}/libversion
)
add_executable(doxmlparser_metrics
main.cpp
)
target_link_libraries(doxmlparser_metrics
doxmlparser
doxygen_version
qtools
${COVERAGE_LINKER_FLAGS}
)

View File

@ -0,0 +1,271 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2006 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
/*! \mainpage Metrics
* This is a small example that shows how to use doxygen's XML output and
* the doxmlparser library. The example shows some very basic code metrics.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <doxmlintf.h>
#include "version.h"
bool isDocumented(IDocRoot *brief,IDocRoot *detailed)
{
bool found=false;
if (brief)
{
IDocIterator *docIt = brief->contents();
if (docIt->current()) // method has brief description
{
found=true;
}
docIt->release();
}
if (detailed && !found)
{
IDocIterator *docIt = detailed->contents();
if (docIt->current())
{
found=true;
}
docIt->release();
}
return found;
}
int main(int argc,char **argv)
{
int locArgc = argc;
if (locArgc == 2)
{
if (!strcmp(argv[1],"--help"))
{
printf("Usage: %s xml_dir\n",argv[0]);
exit(0);
}
else if (!strcmp(argv[1],"--version"))
{
printf("%s version: %s\n",argv[0],getFullVersion());
exit(0);
}
}
if (locArgc!=2)
{
printf("Usage: %s xml_dir\n",argv[0]);
exit(1);
}
int numClasses=0;
int numDocClasses=0;
int numStructs=0;
int numUnions=0;
int numInterfaces=0;
int numExceptions=0;
int numNamespaces=0;
int numFiles=0;
int numGroups=0;
int numPages=0;
int numPackages=0;
int numPubMethods=0;
int numProMethods=0;
int numPriMethods=0;
int numDocPubMethods=0;
int numDocProMethods=0;
int numDocPriMethods=0;
int numFunctions=0;
int numAttributes=0;
int numVariables=0;
int numDocFunctions=0;
int numDocAttributes=0;
int numDocVariables=0;
int numParams=0;
IDoxygen *dox = createObjectModel();
dox->setDebugLevel(0);
if (!dox->readXMLDir(argv[1]))
{
printf("Error reading %s/index.xml\n",argv[1]);
exit(1);
}
ICompoundIterator *cli = dox->compounds();
ICompound *comp;
for (cli->toFirst();(comp=cli->current());cli->toNext())
{
printf("Processing %s...\n",comp->name()->latin1());
bool hasDocs = isDocumented(comp->briefDescription(),comp->detailedDescription());
switch (comp->kind())
{
case ICompound::Class:
numClasses++;
if (hasDocs) numDocClasses++;
break;
case ICompound::Struct: numStructs++; break;
case ICompound::Union: numUnions++; break;
case ICompound::Interface: numInterfaces++; break;
case ICompound::Exception: numExceptions++; break;
case ICompound::Namespace: numNamespaces++; break;
case ICompound::File: numFiles++; break;
case ICompound::Group: numGroups++; break;
case ICompound::Page: numPages++; break;
default: break;
}
ISectionIterator *sli = comp->sections();
ISection *sec;
for (sli->toFirst();(sec=sli->current());sli->toNext())
{
IMemberIterator *mli = sec->members();
IMember *mem;
for (mli->toFirst();(mem=mli->current());mli->toNext())
{
IParamIterator *pli = mem->parameters();
IParam *par;
if (comp->kind()==ICompound::Class ||
comp->kind()==ICompound::Struct ||
comp->kind()==ICompound::Interface
)
{
if (mem->kind()==IMember::Function ||
mem->kind()==IMember::Prototype ||
mem->kind()==IMember::Signal ||
mem->kind()==IMember::Slot ||
mem->kind()==IMember::DCOP
) // is a "method"
{
if (mem->section()->isPublic())
{
numPubMethods++;
if (isDocumented(mem->briefDescription(),mem->detailedDescription()))
{
numDocPubMethods++;
}
}
else if (mem->section()->isProtected())
{
numProMethods++;
if (isDocumented(mem->briefDescription(),mem->detailedDescription()))
{
numDocProMethods++;
}
}
else if (mem->section()->isPrivate())
{
numPriMethods++;
if (isDocumented(mem->briefDescription(),mem->detailedDescription()))
{
numDocPriMethods++;
}
}
}
else if (mem->kind()==IMember::Variable ||
mem->kind()==IMember::Property
) // is an "attribute"
{
numAttributes++;
if (isDocumented(mem->briefDescription(),mem->detailedDescription()))
{
numDocAttributes++;
}
}
}
else if (comp->kind()==ICompound::File ||
comp->kind()==ICompound::Namespace
)
{
if (mem->kind()==IMember::Function ||
mem->kind()==IMember::Prototype ||
mem->kind()==IMember::Signal ||
mem->kind()==IMember::Slot ||
mem->kind()==IMember::DCOP
) // is a "method"
{
numFunctions++;
if (isDocumented(mem->briefDescription(),mem->detailedDescription()))
{
numDocFunctions++;
}
}
else if (mem->kind()==IMember::Variable ||
mem->kind()==IMember::Property
) // is an "attribute"
{
numVariables++;
if (isDocumented(mem->briefDescription(),mem->detailedDescription()))
{
numDocVariables++;
}
}
}
for (pli->toFirst();(par=pli->current());pli->toNext())
{
numParams++;
}
const char *type = mem->typeString()->latin1();
if (type && strcmp(type, "void"))
{
numParams++; // count non-void return types as well
}
pli->release();
}
mli->release();
}
sli->release();
comp->release();
}
cli->release();
dox->release();
int numMethods = numPubMethods+numProMethods+numPriMethods;
int numDocMethods = numDocPubMethods+numDocProMethods+numDocPriMethods;
printf("Metrics:\n");
printf("-----------------------------------\n");
if (numClasses>0) printf("Classes: %10d (%d documented)\n",numClasses,numDocClasses);
if (numStructs>0) printf("Structs: %10d\n",numStructs);
if (numUnions>0) printf("Unions: %10d\n",numUnions);
if (numInterfaces>0) printf("Interfaces: %10d\n",numInterfaces);
if (numExceptions>0) printf("Exceptions: %10d\n",numExceptions);
if (numNamespaces>0) printf("Namespaces: %10d\n",numNamespaces);
if (numFiles>0) printf("Files: %10d\n",numFiles);
if (numGroups>0) printf("Groups: %10d\n",numGroups);
if (numPages>0) printf("Pages: %10d\n",numPages);
if (numPackages>0) printf("Packages: %10d\n",numPackages);
if (numMethods>0) printf("Methods: %10d (%d documented)\n",numMethods,numDocMethods);
if (numPubMethods>0) printf(" Public: %10d (%d documented)\n",numPubMethods,numDocPubMethods);
if (numProMethods>0) printf(" Protected: %10d (%d documented)\n",numProMethods,numDocProMethods);
if (numPriMethods>0) printf(" Private: %10d (%d documented)\n",numPriMethods,numDocPriMethods);
if (numFunctions>0) printf("Functions: %10d (%d documented)\n",numFunctions,numDocFunctions);
if (numAttributes>0) printf("Attributes: %10d (%d documented)\n",numAttributes,numDocAttributes);
if (numVariables>0) printf("Variables: %10d (%d documented)\n",numVariables,numDocVariables);
if (numParams>0) printf("Params: %10d\n",numParams);
printf("-----------------------------------\n");
if (numClasses>0) printf("Avg. #methods/compound: %10f\n",(double)numMethods/(double)numClasses);
if (numMethods>0) printf("Avg. #params/method: %10f\n",(double)numParams/(double)numMethods);
printf("-----------------------------------\n");
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
include_directories(
.
../include
${PROJECT_SOURCE_DIR}/qtools
)
add_library(doxmlparser STATIC
basehandler.cpp
compoundhandler.cpp
debug.cpp
dochandler.cpp
graphhandler.cpp
linkedtexthandler.cpp
loamhandler.cpp
mainhandler.cpp
memberhandler.cpp
paramhandler.cpp
sectionhandler.cpp
)

View File

@ -0,0 +1,3 @@
#include "basehandler.h"
QXmlLocator * LocatorContainer::s_theLocator=0;

View File

@ -0,0 +1,325 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef _BASEHANDLER_H
#define _BASEHANDLER_H
#include <qxml.h>
#include <qdict.h>
#include <qstring.h>
#include "debug.h"
//-----------------------------------------------------------------------------
class IBaseHandler
{
public:
virtual void setDelegate(QXmlDefaultHandler *delegate) = 0;
virtual QXmlDefaultHandler *delegate() const = 0;
virtual ~IBaseHandler() {}
};
//-----------------------------------------------------------------------------
class IFallBackHandler
{
public:
virtual bool handleStartElement(const QString & name,
const QXmlAttributes & attrib) = 0;
virtual bool handleEndElement(const QString &name) = 0;
virtual ~IFallBackHandler() {}
};
//-----------------------------------------------------------------------------
template<class T> class ElementMapper
{
class StartElementHandler
{
typedef void (T::*Handler)(const QXmlAttributes &attrib);
public:
StartElementHandler() : m_parent(0) {}
StartElementHandler(T *parent, Handler h)
: m_parent(parent), m_handler(h) {}
void operator()(const QXmlAttributes &attrib)
{ if (m_parent) (m_parent->*m_handler)(attrib); }
private:
T *m_parent = 0;
Handler m_handler;
};
class EndElementHandler
{
typedef void (T::*Handler)();
public:
EndElementHandler() : m_parent(0) {}
EndElementHandler(T *parent, Handler h)
: m_parent(parent), m_handler(h) {}
void operator()()
{ if (m_parent) (m_parent->*m_handler)(); }
private:
T *m_parent = 0;
Handler m_handler;
};
public:
typedef StartElementHandler StartElementHandlerT;
typedef EndElementHandler EndElementHandlerT;
ElementMapper() : m_startHandlers(67), m_endHandlers(67)
{
m_startHandlers.setAutoDelete(TRUE);
m_endHandlers.setAutoDelete(TRUE);
}
virtual ~ElementMapper()
{
}
void addStartHandler(const char *key)
{
m_startHandlers.insert(key,new StartElementHandlerT);
}
void addStartHandler(const char *key, T *obj, void (T::*handler)(const QXmlAttributes &))
{
m_startHandlers.insert(key,new StartElementHandlerT(obj,handler));
}
void addEndHandler(const char *key)
{
m_endHandlers.insert(key,new EndElementHandlerT);
}
void addEndHandler(const char *key, T *obj, void (T::*handler)())
{
m_endHandlers.insert(key,new EndElementHandlerT(obj,handler));
}
protected:
QDict<StartElementHandlerT> m_startHandlers;
QDict<EndElementHandlerT> m_endHandlers;
};
//-----------------------------------------------------------------------------
struct LocatorContainer
{
static QXmlLocator *s_theLocator;
};
//-----------------------------------------------------------------------------
template<class T> class BaseHandler : public QXmlDefaultHandler,
public ElementMapper<T>,
public LocatorContainer,
public IBaseHandler
{
public:
typedef typename ElementMapper<T>::StartElementHandlerT StartElementHandlerT;
typedef typename ElementMapper<T>::EndElementHandlerT EndElementHandlerT;
BaseHandler() : m_skipCount(0), m_delegateHandler(0), m_fallBackHandler(0)
{
}
virtual ~BaseHandler()
{
ASSERT(m_delegateHandler==0);
}
virtual bool startDocument()
{
return TRUE;
}
virtual bool startElement( const QString & namespaceURI,
const QString & localName,
const QString & name,
const QXmlAttributes & attrib
)
{
if (m_delegateHandler)
{
return m_delegateHandler->startElement(namespaceURI,localName,name,attrib);
}
if (!m_skipUntil.isEmpty()) // skip mode
{
if (m_skipUntil==name) m_skipCount++;
debug(1,"line %d, col %d: skipping start tag %s count=%d\n",
s_theLocator->lineNumber(),s_theLocator->columnNumber(),
name.data(),m_skipCount);
return TRUE;
}
StartElementHandlerT *handler = ElementMapper<T>::m_startHandlers[name.utf8()];
if (handler)
{
(*handler)(attrib);
//printf("found start tag %s\n",name.data());
}
else if (!m_fallBackHandler ||
!m_fallBackHandler->handleStartElement(name,attrib)
)
{
debug(1,"line %d, col %d: found unexpected tag '%s', skipping until matching end tag\n",
s_theLocator->lineNumber(),s_theLocator->columnNumber(),
name.data());
m_skipUntil = name;
m_skipCount=1;
}
return TRUE;
}
virtual bool endElement( const QString& namespaceURI, const QString& localName, const QString& name )
{
if (m_delegateHandler)
{
return m_delegateHandler->endElement(namespaceURI,localName,name);
}
if (name==m_skipUntil)
{
m_skipCount--;
debug(1,"line %d, col %d: skipping end tag %s count=%d\n",
s_theLocator->lineNumber(),s_theLocator->columnNumber(),
name.data(),m_skipCount);
if (m_skipCount==0)
{
m_skipUntil="";
}
//printf("found end tag %s\n",name.data());
}
else if (m_skipUntil.isEmpty())
{
EndElementHandlerT *handler = ElementMapper<T>::m_endHandlers[name.utf8()];
if (handler)
{
(*handler)();
//printf("found end tag %s\n",name.data());
}
else if (m_fallBackHandler)
{
m_fallBackHandler->handleEndElement(name);
}
}
m_curString="";
return TRUE;
}
bool skippedEntity ( const QString &s )
{
if (m_delegateHandler)
{
return m_delegateHandler->skippedEntity(s);
}
debug(1,"line %d, col %d: Skipped unhandled entity %s\n",
s_theLocator->lineNumber(),s_theLocator->columnNumber(),
s.data());
return TRUE;
}
/*! called when a number of characters are received by the parser.
* \param ch the characters.
*/
virtual bool characters ( const QString & ch )
{
if (m_delegateHandler)
{
return m_delegateHandler->characters(ch);
}
//printf("Found characters \"%s\"\n",ch.data());
m_curString+=ch;
return TRUE;
}
void setDelegate(QXmlDefaultHandler *delegate)
{
m_delegateHandler = delegate;
}
QXmlDefaultHandler *delegate() const
{
return m_delegateHandler;
}
void setFallBackHandler(IFallBackHandler *h)
{
m_fallBackHandler = h;
}
IFallBackHandler *fallBackHandler() const
{
return m_fallBackHandler;
}
void setDocumentLocator( QXmlLocator * locator )
{
debug(2,"setDocumentLocator(%p)\n",locator);
s_theLocator = locator;
}
protected:
QString m_curString;
QString m_skipUntil;
int m_skipCount = 0;
QXmlDefaultHandler *m_delegateHandler = 0;
IFallBackHandler *m_fallBackHandler = 0;
};
//-----------------------------------------------------------------------------
template<class T> class BaseFallBackHandler : public ElementMapper<T>,
public IFallBackHandler
{
public:
typedef typename ElementMapper<T>::StartElementHandlerT StartElementHandlerT;
typedef typename ElementMapper<T>::EndElementHandlerT EndElementHandlerT;
BaseFallBackHandler()
{
}
virtual ~BaseFallBackHandler()
{
}
bool handleStartElement(const QString & name,
const QXmlAttributes & attrib)
{
StartElementHandlerT *handler = ElementMapper<T>::m_startHandlers[name.utf8()];
if (handler)
{
(*handler)(attrib);
return TRUE;
}
return FALSE;
}
bool handleEndElement(const QString &name)
{
EndElementHandlerT *handler = ElementMapper<T>::m_endHandlers[name.utf8()];
if (handler)
{
(*handler)();
return TRUE;
}
return FALSE;
}
};
#endif

View File

@ -0,0 +1,50 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef BASEITERATOR_H
#define BASEITERATOR_H
#include <qlist.h>
#include <doxmlintf.h>
template<class Intf,class ElemIntf,class ElemImpl> class BaseIterator :
public Intf, public QListIterator<ElemImpl>
{
public:
BaseIterator(const QList<ElemImpl> &list) : QListIterator<ElemImpl>(list) {}
virtual ~BaseIterator() {}
virtual ElemIntf *toFirst() { return QListIterator<ElemImpl>::toFirst(); }
virtual ElemIntf *toLast() { return QListIterator<ElemImpl>::toLast(); }
virtual ElemIntf *toNext() { return QListIterator<ElemImpl>::operator++(); }
virtual ElemIntf *toPrev() { return QListIterator<ElemImpl>::operator--(); }
virtual ElemIntf *current() const { return QListIterator<ElemImpl>::current(); }
virtual void release() { delete this; }
};
template<class Intf,class ElemIntf,class ElemImpl,class Intermediate>
class BaseIteratorVia :
public Intf, public QListIterator<ElemImpl>
{
public:
BaseIteratorVia(const QList<ElemImpl> &list) : QListIterator<ElemImpl>(list) {}
virtual ~BaseIteratorVia() {}
virtual ElemIntf *toFirst() { return static_cast<Intermediate *>(QListIterator<ElemImpl>::toFirst()); }
virtual ElemIntf *toLast() { return static_cast<Intermediate *>(QListIterator<ElemImpl>::toLast()); }
virtual ElemIntf *toNext() { return static_cast<Intermediate *>(QListIterator<ElemImpl>::operator++()); }
virtual ElemIntf *toPrev() { return static_cast<Intermediate *>(QListIterator<ElemImpl>::operator--()); }
virtual ElemIntf *current() const { return static_cast<Intermediate *>(QListIterator<ElemImpl>::current()); }
virtual void release() { delete this; }
};
#endif

View File

@ -0,0 +1,655 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include "mainhandler.h"
#include "compoundhandler.h"
#include "dochandler.h"
#include "debug.h"
#include "graphhandler.h"
#include "sectionhandler.h"
#include "paramhandler.h"
#include "loamhandler.h"
#include "memberhandler.h"
#include "linkedtexthandler.h"
//----------------------------------------------------------------------------
IncludeHandler::IncludeHandler(IBaseHandler *parent,const char *endtag) :
m_parent(parent)
{
addEndHandler(endtag,this,&IncludeHandler::endInclude);
}
IncludeHandler::~IncludeHandler()
{
}
void IncludeHandler::startInclude(const QXmlAttributes &attrib)
{
m_curString = "";
m_refId = attrib.value("refid");
m_isLocal = attrib.value("local")=="yes";
m_parent->setDelegate(this);
}
void IncludeHandler::endInclude()
{
m_name = m_curString;
m_parent->setDelegate(0);
debug(2,"Found include %s\n",m_name.data());
}
//----------------------------------------------------------------------------
class CompoundIdIterator : public ICompoundIterator,
public QListIterator<QString>
{
public:
CompoundIdIterator(const MainHandler *m,const QList<QString> &list) :
QListIterator<QString>(list), m_mainHandler(m) {}
virtual ~CompoundIdIterator() {}
virtual void toFirst()
{
QListIterator<QString>::toFirst();
}
virtual void toLast()
{
QListIterator<QString>::toLast();
}
virtual void toNext()
{
QListIterator<QString>::operator++();
}
virtual void toPrev()
{
QListIterator<QString>::operator--();
}
virtual ICompound *current() const
{
QString *id = QListIterator<QString>::current();
return id ? m_mainHandler->compoundById(id->utf8()) : 0;
}
virtual void release()
{ delete this; }
private:
const MainHandler *m_mainHandler = 0;
};
//----------------------------------------------------------------------------
ICompound *RelatedCompound::compound() const
{
return m_parent->m_mainHandler->compoundById(m_id.utf8());
}
//----------------------------------------------------------------------------
class CompoundErrorHandler : public QXmlErrorHandler
{
public:
virtual ~CompoundErrorHandler() {}
bool warning( const QXmlParseException & )
{
return FALSE;
}
bool error( const QXmlParseException & )
{
return FALSE;
}
bool fatalError( const QXmlParseException &exception )
{
debug(1,"Fatal error at line %d column %d: %s\n",
exception.lineNumber(),exception.columnNumber(),
exception.message().data());
return FALSE;
}
QString errorString() { return ""; }
private:
QString errorMsg;
};
//----------------------------------------------------------------------------
class CompoundTypeMap
{
public:
CompoundTypeMap()
{
m_map.setAutoDelete(TRUE);
m_map.insert("class", new int(ICompound::Class));
m_map.insert("struct", new int(ICompound::Struct));
m_map.insert("union", new int(ICompound::Union));
m_map.insert("interface",new int(ICompound::Interface));
m_map.insert("protocol", new int(ICompound::Protocol));
m_map.insert("category", new int(ICompound::Category));
m_map.insert("exception",new int(ICompound::Exception));
m_map.insert("file", new int(ICompound::File));
m_map.insert("namespace",new int(ICompound::Namespace));
m_map.insert("group", new int(ICompound::Group));
m_map.insert("page", new int(ICompound::Page));
m_map.insert("example", new int(ICompound::Example));
m_map.insert("dir", new int(ICompound::Dir));
}
virtual ~CompoundTypeMap()
{
}
ICompound::CompoundKind map(const QString &s)
{
int *val = m_map.find(s.utf8());
if (val==0)
{
debug(1,"Warning: '%s' is an invalid compound type\n",s.data());
return ICompound::Invalid;
}
else return (ICompound::CompoundKind)*val;
}
private:
QDict<int> m_map;
};
static CompoundTypeMap *s_typeMap;
void compoundhandler_init()
{
s_typeMap = new CompoundTypeMap;
}
void compoundhandler_exit()
{
delete s_typeMap;
}
//----------------------------------------------------------------------------
CompoundHandler::CompoundHandler(const QString &xmlDir)
: m_titleHandler(0),
m_includeDependencyGraph(0),
m_includedByDependencyGraph(0),
m_templateParamList(0),
m_brief(0),
m_detailed(0),
m_inheritanceGraph(0),
m_collaborationGraph(0),
m_programListing(0),
m_members(0),
m_xmlDir(xmlDir),
m_refCount(1),
m_memberDict(257),
m_memberNameDict(257),
m_mainHandler(0)
{
m_superClasses.setAutoDelete(TRUE);
m_subClasses.setAutoDelete(TRUE);
m_sections.setAutoDelete(TRUE);
m_memberNameDict.setAutoDelete(TRUE);
m_innerCompounds.setAutoDelete(TRUE);
m_includes.setAutoDelete(TRUE);
m_includedBy.setAutoDelete(TRUE);
addStartHandler("doxygen");
addEndHandler("doxygen");
addStartHandler("compounddef",this,&CompoundHandler::startCompound);
addEndHandler("compounddef",this,&CompoundHandler::endCompound);
addStartHandler("compoundname");
addEndHandler("compoundname",this,&CompoundHandler::endCompoundName);
addStartHandler("title",this,&CompoundHandler::startTitle);
addStartHandler("basecompoundref",this,&CompoundHandler::startSuperClass);
addEndHandler("basecompoundref",this,&CompoundHandler::endSuperClass);
addStartHandler("derivedcompoundref",this,&CompoundHandler::startSubClass);
addEndHandler("derivedcompoundref",this,&CompoundHandler::endSubClass);
addStartHandler("includes",this,&CompoundHandler::startIncludes);
addStartHandler("includedby",this,&CompoundHandler::startIncludedBy);
addStartHandler("incdepgraph",this,&CompoundHandler::startIncludeDependencyGraph);
addStartHandler("invincdepgraph",this,&CompoundHandler::startIncludedByDependencyGraph);
addStartHandler("innerdir",this,&CompoundHandler::startInnerDir);
addEndHandler("innerdir");
addStartHandler("innerfile",this,&CompoundHandler::startInnerFile);
addEndHandler("innerfile");
addStartHandler("innerclass",this,&CompoundHandler::startInnerClass);
addEndHandler("innerclass");
addStartHandler("innernamespace",this,&CompoundHandler::startInnerNamespace);
addEndHandler("innernamespace");
addStartHandler("innerpage",this,&CompoundHandler::startInnerPage);
addEndHandler("innerpage");
addStartHandler("innergroup",this,&CompoundHandler::startInnerGroup);
addEndHandler("innergroup");
addStartHandler("templateparamlist",this,&CompoundHandler::startTemplateParamList);
addStartHandler("sectiondef",this,&CompoundHandler::startSection);
addStartHandler("briefdescription",this,&CompoundHandler::startBriefDesc);
addStartHandler("detaileddescription",this,&CompoundHandler::startDetailedDesc);
addStartHandler("inheritancegraph",this,&CompoundHandler::startInheritanceGraph);
addStartHandler("collaborationgraph",this,&CompoundHandler::startCollaborationGraph);
addStartHandler("programlisting",this,&CompoundHandler::startProgramListing);
addStartHandler("location",this,&CompoundHandler::startLocation);
addEndHandler("location");
addStartHandler("listofallmembers",this,&CompoundHandler::startListOfAllMembers);
}
CompoundHandler::~CompoundHandler()
{
debug(2,"CompoundHandler::~CompoundHandler()\n");
delete m_titleHandler;
delete m_brief;
delete m_detailed;
delete m_programListing;
delete m_inheritanceGraph;
delete m_collaborationGraph;
delete m_includeDependencyGraph;
delete m_includedByDependencyGraph;
delete m_templateParamList;
delete m_members;
}
void CompoundHandler::startSection(const QXmlAttributes& attrib)
{
SectionHandler *sectHandler = new SectionHandler(this);
sectHandler->startSection(attrib);
m_sections.append(sectHandler);
}
void CompoundHandler::startBriefDesc(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_brief = docHandler;
}
void CompoundHandler::startDetailedDesc(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_detailed = docHandler;
}
void CompoundHandler::startProgramListing(const QXmlAttributes& attrib)
{
ProgramListingHandler *plHandler = new ProgramListingHandler(this);
plHandler->startProgramListing(attrib);
m_programListing = plHandler;
}
void CompoundHandler::startIncludes(const QXmlAttributes& attrib)
{
IncludeHandler *inc = new IncludeHandler(this,"includes");
m_includes.append(inc);
inc->startInclude(attrib);
}
void CompoundHandler::startIncludedBy(const QXmlAttributes& attrib)
{
IncludeHandler *inc = new IncludeHandler(this,"includedby");
m_includedBy.append(inc);
inc->startInclude(attrib);
}
void CompoundHandler::startCompound(const QXmlAttributes& attrib)
{
m_id = attrib.value("id");
m_kindString = attrib.value("kind");
m_kind = s_typeMap->map(m_kindString);
m_protection = attrib.value("prot");
debug(2,"startCompound(id='%s' type='%s')\n",m_id.data(),m_kindString.data());
}
void CompoundHandler::endCompound()
{
debug(2,"endCompound()\n");
}
void CompoundHandler::startLocation(const QXmlAttributes& attrib)
{
m_defFile = attrib.value("file");
m_defLine = attrib.value("line").toInt();
m_defBodyFile = attrib.value("bodyfile");
m_defBodyStart = attrib.value("bodystart").toInt();
m_defBodyEnd = attrib.value("bodyend").toInt();
}
void CompoundHandler::endCompoundName()
{
m_name = m_curString.stripWhiteSpace();
debug(2,"Compound name '%s'\n",m_name.data());
}
void CompoundHandler::startInnerClass(const QXmlAttributes& attrib)
{
m_innerCompounds.append(new QString(attrib.value("refid")));
}
void CompoundHandler::startInnerNamespace(const QXmlAttributes& attrib)
{
m_innerCompounds.append(new QString(attrib.value("refid")));
}
void CompoundHandler::startInnerFile(const QXmlAttributes& attrib)
{
m_innerCompounds.append(new QString(attrib.value("refid")));
}
void CompoundHandler::startInnerGroup(const QXmlAttributes& attrib)
{
m_innerCompounds.append(new QString(attrib.value("refid")));
}
void CompoundHandler::startInnerPage(const QXmlAttributes& attrib)
{
m_innerCompounds.append(new QString(attrib.value("refid")));
}
void CompoundHandler::startInnerDir(const QXmlAttributes& attrib)
{
m_innerCompounds.append(new QString(attrib.value("refid")));
}
void CompoundHandler::startTemplateParamList(const QXmlAttributes& attrib)
{
m_templateParamList = new TemplateParamListHandler(this);
m_templateParamList->startTemplateParamList(attrib);
}
void CompoundHandler::startListOfAllMembers(const QXmlAttributes& attrib)
{
m_members = new ListOfAllMembersHandler(this);
m_members->startListOfAllMembers(attrib);
}
void CompoundHandler::startSuperClass(const QXmlAttributes& attrib)
{
IRelatedCompound::Protection prot = IRelatedCompound::Public;
QString protString = attrib.value("prot");
if (protString=="protected")
{
prot = IRelatedCompound::Protected;
}
else if (protString=="private")
{
prot = IRelatedCompound::Private;
}
IRelatedCompound::Kind kind = IRelatedCompound::Normal;
QString kindString = attrib.value("virt");
if (kindString=="virtual") kind = IRelatedCompound::Virtual;
RelatedCompound *sc=new RelatedCompound(
this,
attrib.value("refid"),
prot,
kind
);
debug(2,"super class id='%s' prot='%s' virt='%s'\n",
attrib.value("refid").data(),
protString.data(),
kindString.data());
m_superClasses.append(sc);
m_curString = "";
}
void CompoundHandler::endSuperClass()
{
m_superClasses.getLast()->setName(m_curString);
}
void CompoundHandler::startSubClass(const QXmlAttributes& attrib)
{
IRelatedCompound::Protection prot = IRelatedCompound::Public;
QString protString = attrib.value("prot");
if (protString=="protected") prot = IRelatedCompound::Protected;
else if (protString=="private") prot = IRelatedCompound::Private;
IRelatedCompound::Kind kind = IRelatedCompound::Normal;
QString kindString = attrib.value("virt");
if (kindString=="virtual") kind = IRelatedCompound::Virtual;
RelatedCompound *sc = new RelatedCompound(
this,
attrib.value("refid"),
prot,
kind
);
debug(2,"sub class id='%s' prot='%s' virt='%s'\n",
attrib.value("refid").data(),
protString.data(),
kindString.data());
m_subClasses.append(sc);
m_curString = "";
}
void CompoundHandler::endSubClass()
{
m_subClasses.getLast()->setName(m_curString);
}
void CompoundHandler::startTitle(const QXmlAttributes& attrib)
{
ASSERT(m_titleHandler==0);
m_titleHandler = new TitleHandler(this);
m_titleHandler->startTitle(attrib);
}
bool CompoundHandler::parseXML(const char *compId)
{
QFile xmlFile(m_xmlDir+"/"+compId+".xml");
if (!xmlFile.exists()) return FALSE;
CompoundErrorHandler errorHandler;
QXmlInputSource source( xmlFile );
QXmlSimpleReader reader;
reader.setContentHandler( this );
reader.setErrorHandler( &errorHandler );
reader.parse( source );
return TRUE;
}
void CompoundHandler::initialize(MainHandler *mh)
{
m_mainHandler = mh;
QListIterator<SectionHandler> msi(m_sections);
SectionHandler *sec;
for (;(sec=msi.current());++msi)
{
sec->initialize(this);
}
if (m_members)
{
m_members->initialize(mh);
}
}
void CompoundHandler::insertMember(MemberHandler *mh)
{
m_memberDict.insert(mh->id()->latin1(),mh);
mh->initialize(m_mainHandler);
QList<MemberHandler> *mhl = m_memberNameDict.find(mh->id()->latin1());
if (mhl==0)
{
mhl = new QList<MemberHandler>;
m_memberNameDict.insert(mh->name()->latin1(),mhl);
}
mhl->append(mh);
}
ICompound *CompoundHandler::toICompound() const
{
switch (m_kind)
{
case ICompound::Class: return (IClass *)this;
case ICompound::Struct: return (IStruct *)this;
case ICompound::Union: return (IUnion *)this;
case ICompound::Interface: return (IInterface *)this;
case ICompound::Protocol: return (IClass *)this;
case ICompound::Category: return (IClass *)this;
case ICompound::Exception: return (IException *)this;
case ICompound::File: return (IFile *)this;
case ICompound::Namespace: return (INamespace *)this;
case ICompound::Group: return (IGroup *)this;
case ICompound::Page: return (IPage *)this;
case ICompound::Example: return (IPage *)this;
case ICompound::Dir: return (IDir *)this;
default: return 0;
}
return 0;
}
void CompoundHandler::release()
{
debug(2,"CompoundHandler::release() %d->%d\n",m_refCount,m_refCount-1);
if (--m_refCount<=0)
{
m_mainHandler->unloadCompound(this);
delete this;
}
}
ISectionIterator *CompoundHandler::sections() const
{
return new SectionIterator(m_sections);
}
IMemberIterator *CompoundHandler::memberByName(const char *name) const
{
QList<MemberHandler> *ml = m_memberNameDict[name];
if (ml==0) return 0;
return new MemberIterator(*ml);
}
void CompoundHandler::startInheritanceGraph(const QXmlAttributes &attrib)
{
m_inheritanceGraph = new GraphHandler(this,"inheritancegraph");
m_inheritanceGraph->startGraph(attrib);
}
void CompoundHandler::startCollaborationGraph(const QXmlAttributes &attrib)
{
m_collaborationGraph = new GraphHandler(this,"collaborationgraph");
m_collaborationGraph->startGraph(attrib);
}
void CompoundHandler::startIncludeDependencyGraph(const QXmlAttributes &attrib)
{
m_includeDependencyGraph = new GraphHandler(this,"incdepgraph");
m_includeDependencyGraph->startGraph(attrib);
}
void CompoundHandler::startIncludedByDependencyGraph(const QXmlAttributes &attrib)
{
m_includedByDependencyGraph = new GraphHandler(this,"invincdepgraph");
m_includedByDependencyGraph->startGraph(attrib);
}
IDocRoot *CompoundHandler::briefDescription() const
{
return m_brief;
}
IDocRoot *CompoundHandler::detailedDescription() const
{
return m_detailed;
}
IMember *CompoundHandler::memberById(const char *id) const
{
return (IFunction*)m_memberDict[id];
}
IGraph *CompoundHandler::inheritanceGraph() const
{
return m_inheritanceGraph;
}
IGraph *CompoundHandler::collaborationGraph() const
{
return m_collaborationGraph;
}
IGraph *CompoundHandler::includeDependencyGraph() const
{
return m_includeDependencyGraph;
}
IGraph *CompoundHandler::includedByDependencyGraph() const
{
return m_includedByDependencyGraph;
}
IRelatedCompoundIterator *CompoundHandler::baseCompounds() const
{
return new RelatedCompoundIterator(m_superClasses);
}
IRelatedCompoundIterator *CompoundHandler::derivedCompounds() const
{
return new RelatedCompoundIterator(m_subClasses);
}
ICompoundIterator *CompoundHandler::nestedCompounds() const
{
return new CompoundIdIterator(m_mainHandler,m_innerCompounds);
}
IDocProgramListing *CompoundHandler::source() const
{
return m_programListing;
}
IIncludeIterator *CompoundHandler::includes() const
{
return new IncludeIterator(m_includes);
}
IIncludeIterator *CompoundHandler::includedBy() const
{
return new IncludeIterator(m_includedBy);
}
IParamIterator *CompoundHandler::templateParameters() const
{
return m_templateParamList ? m_templateParamList->templateParams() : 0;
}
const IDocTitle *CompoundHandler::title() const
{
return m_titleHandler;
}
IMemberReferenceIterator *CompoundHandler::members() const
{
return m_members ? m_members->members() : 0;
}

View File

@ -0,0 +1,237 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef _COMPOUNDHANDLER_H
#define _COMPOUNDHANDLER_H
#include <qstring.h>
#include <qlist.h>
#include <qxml.h>
#include <doxmlintf.h>
#include "stringimpl.h"
#include "basehandler.h"
#include "baseiterator.h"
class MainHandler;
class DocHandler;
class ProgramListingHandler;
class GraphHandler;
class MemberHandler;
class CompoundHandler;
class SectionHandler;
class ParamHandler;
class TemplateParamListHandler;
class TitleHandler;
class ListOfAllMembersHandler;
class IncludeHandler : public IInclude, public BaseHandler<IncludeHandler>
{
public:
IncludeHandler(IBaseHandler *parent,const char *endtag);
virtual ~IncludeHandler();
void startInclude(const QXmlAttributes &attrib);
void endInclude();
// IInclude
virtual const IString * name() const
{ return &m_name; }
virtual const IString * refId() const
{ return &m_refId; }
virtual bool isLocal() const
{ return m_isLocal; }
private:
IBaseHandler *m_parent = 0;
StringImpl m_name; // element's content
StringImpl m_refId; // refid
bool m_isLocal = false; // local
};
class IncludeIterator : public BaseIterator<IIncludeIterator,IInclude,IncludeHandler>
{
public:
IncludeIterator(const QList<IncludeHandler> &list) :
BaseIterator<IIncludeIterator,IInclude,IncludeHandler>(list) {}
};
class RelatedCompound : public IRelatedCompound
{
public:
RelatedCompound(CompoundHandler *parent,
const QString &id,
Protection prot,
Kind kind
) :
m_parent(parent), m_id(id), m_protection(prot), m_kind(kind) {}
virtual ~RelatedCompound() {}
void setName(const QString &str) { m_name = str; }
virtual ICompound *compound() const;
virtual Protection protection() const { return m_protection; }
virtual Kind kind() const { return m_kind; }
virtual const IString *name() const { return &m_name; }
private:
CompoundHandler *m_parent = 0;
QString m_id; // refid
Protection m_protection = Public; // prot
Kind m_kind = Normal; // virt
StringImpl m_name; // element's content
};
class RelatedCompoundIterator : public BaseIterator<IRelatedCompoundIterator,IRelatedCompound,RelatedCompound>
{
public:
RelatedCompoundIterator(const QList<RelatedCompound> &list) :
BaseIterator<IRelatedCompoundIterator,IRelatedCompound,RelatedCompound>(list) {}
};
class CompoundHandler : public IClass,
public IStruct,
public IUnion,
public IException,
public IInterface,
public INamespace,
public IFile,
public IGroup,
public IPage,
public IDir,
public BaseHandler<CompoundHandler>
{
friend class RelatedCompound;
public:
virtual void startSection(const QXmlAttributes& attrib);
virtual void startCompound(const QXmlAttributes& attrib);
virtual void startSuperClass(const QXmlAttributes& attrib);
virtual void endSuperClass();
virtual void startSubClass(const QXmlAttributes& attrib);
virtual void endSubClass();
virtual void endCompound();
virtual void endCompoundName();
virtual void startBriefDesc(const QXmlAttributes& attrib);
virtual void startDetailedDesc(const QXmlAttributes& attrib);
virtual void startLocation(const QXmlAttributes& attrib);
virtual void startProgramListing(const QXmlAttributes& attrib);
virtual void startInheritanceGraph(const QXmlAttributes& attrib);
virtual void startCollaborationGraph(const QXmlAttributes& attrib);
virtual void startIncludeDependencyGraph(const QXmlAttributes& attrib);
virtual void startIncludedByDependencyGraph(const QXmlAttributes& attrib);
virtual void startIncludes(const QXmlAttributes& attrib);
virtual void startIncludedBy(const QXmlAttributes& attrib);
virtual void startInnerDir(const QXmlAttributes& attrib);
virtual void startInnerClass(const QXmlAttributes& attrib);
virtual void startInnerNamespace(const QXmlAttributes& attrib);
virtual void startInnerFile(const QXmlAttributes& attrib);
virtual void startInnerGroup(const QXmlAttributes& attrib);
virtual void startInnerPage(const QXmlAttributes& attrib);
virtual void startTitle(const QXmlAttributes& attrib);
virtual void startTemplateParamList(const QXmlAttributes& attrib);
virtual void startListOfAllMembers(const QXmlAttributes& attrib);
virtual void addref() { m_refCount++; }
CompoundHandler(const QString &dirName);
virtual ~CompoundHandler();
bool parseXML(const char *compId);
void initialize(MainHandler *mh);
void insertMember(MemberHandler *mh);
ICompound *toICompound() const;
// ICompound implementation
const IString *name() const { return &m_name; }
const IString *id() const { return &m_id; }
CompoundKind kind() const { return m_kind; }
const IString *kindString() const { return &m_kindString; }
ISectionIterator *sections() const;
IDocRoot *briefDescription() const;
IDocRoot *detailedDescription() const;
IMember *memberById(const char *id) const;
IMemberIterator *memberByName(const char *name) const;
IParamIterator *templateParameters() const;
void release();
// IClass implementation
IGraph *inheritanceGraph() const;
IGraph *collaborationGraph() const;
IRelatedCompoundIterator *baseCompounds() const;
IRelatedCompoundIterator *derivedCompounds() const;
ICompoundIterator *nestedCompounds() const;
ICompoundIterator *nestedGroup() const;
const IString *locationFile() const { return &m_defFile; }
int locationLine() const { return m_defLine; }
const IString *locationBodyFile() const { return &m_defBodyFile; }
int locationBodyStartLine() const { return m_defBodyStart; }
int locationBodyEndLine() const { return m_defBodyEnd; }
IMemberReferenceIterator *members() const;
// IFile implementation
IGraph *includeDependencyGraph() const;
IGraph *includedByDependencyGraph() const;
IDocProgramListing *source() const;
IIncludeIterator *includes() const;
IIncludeIterator *includedBy() const;
// IPage implementation
const IDocTitle *title() const;
private:
// XML elements:
// -------------
StringImpl m_name; // compoundname
TitleHandler* m_titleHandler = 0; // title
QList<RelatedCompound> m_subClasses; // basecompoundref
QList<RelatedCompound> m_superClasses; // derivedcompoundref
QList<IncludeHandler> m_includes; // includes
QList<IncludeHandler> m_includedBy; // includedBy
GraphHandler* m_includeDependencyGraph = 0;// incdepgraph
GraphHandler* m_includedByDependencyGraph = 0; // invincdepgraph
QList<QString> m_innerCompounds; // innerdir/innerfile/innerclass/innernamespace/innergroup
TemplateParamListHandler* m_templateParamList; // templateparamlist
QList<SectionHandler> m_sections; // sectiondef
DocHandler* m_brief = 0; // briefdescription
DocHandler* m_detailed = 0; // detaileddescription
GraphHandler* m_inheritanceGraph = 0; // inheritancegraph
GraphHandler* m_collaborationGraph = 0; // collaborationgraph
ProgramListingHandler* m_programListing = 0; // programlisting
// location
StringImpl m_defFile; // - file
int m_defLine = 0; // - line
StringImpl m_defBodyFile; // - bodyfile
int m_defBodyStart = 0; // - bodystart
int m_defBodyEnd = 0; // - bodyend
ListOfAllMembersHandler* m_members = 0; // listofallmember
// XML attributes:
// ---------------
StringImpl m_id; // id
CompoundKind m_kind = Invalid; // kind
StringImpl m_kindString; // kind as a string
StringImpl m_protection; // prot
// local variables
QString m_xmlDir; // directory where the info is found
int m_refCount = 0; // object reference counter
QDict<MemberHandler> m_memberDict; // id->member lookup
QDict<QList<MemberHandler> > m_memberNameDict; // name->memberlist lookup
MainHandler* m_mainHandler = 0; // parent object
};
void compoundhandler_init();
void compoundhandler_exit();
#endif

View File

@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "debug.h"
static int s_debugLevel = 0;
void debug(int level,const char *msg,...)
{
if (level<=s_debugLevel)
{
va_list args;
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
}
}
void setDebugLevel(int level)
{
s_debugLevel = level;
}

View File

@ -0,0 +1,7 @@
#ifndef _DEBUG_H
#define _DEBUG_H
void debug(int level,const char *msg,...);
void setDebugLevel(int level);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,216 @@
#include "graphhandler.h"
class EdgeRelationMapper
{
public:
EdgeRelationMapper()
{
m_map.insert("public-inheritance", IChildNode::PublicInheritance);
m_map.insert("protected-inheritance", IChildNode::ProtectedInheritance);
m_map.insert("private-inheritance", IChildNode::PrivateInheritance);
m_map.insert("usage", IChildNode::Usage);
m_map.insert("template-instance", IChildNode::TemplateInstance);
}
IChildNode::NodeRelation stringToNodeRelation(const QString &nrStr)
{
return m_map[nrStr];
}
private:
QMap<QString,IChildNode::NodeRelation> m_map;
};
static EdgeRelationMapper *s_edgeRelationMapper;
void graphhandler_init()
{
s_edgeRelationMapper = new EdgeRelationMapper;
}
void graphhandler_exit()
{
delete s_edgeRelationMapper;
}
//------------------------------------------------------------------------
GraphHandler::GraphHandler(IBaseHandler *parent,const char *endTag)
: m_parent(parent)
{
addEndHandler(endTag,this,&GraphHandler::endGraph);
addStartHandler("node",this,&GraphHandler::startNode);
m_nodes.setAutoDelete(TRUE);
m_nodeDict = new QDict<NodeHandler>(1009);
}
GraphHandler::~GraphHandler()
{
delete m_nodeDict;
}
void GraphHandler::startGraph(const QXmlAttributes &)
{
debug(2,"startGraph\n");
m_parent->setDelegate(this);
}
void GraphHandler::endGraph()
{
debug(2,"endGraph\n");
m_parent->setDelegate(0);
}
void GraphHandler::startNode(const QXmlAttributes &attrib)
{
NodeHandler *n = new NodeHandler(this);
n->startNode(attrib);
m_nodes.append(n);
m_nodeDict->insert(attrib.value("id").utf8(),n);
}
INodeIterator *GraphHandler::nodes() const
{
return new NodeIterator(*this);
}
NodeHandler *GraphHandler::getNodeById(const QString &id) const
{
return m_nodeDict->find(id.utf8());
}
//------------------------------------------------------------------------
NodeHandler::NodeHandler(GraphHandler *gh)
: m_parent(gh), m_graph(gh)
{
addEndHandler("node",this,&NodeHandler::endNode);
addStartHandler("link",this,&NodeHandler::startLink);
addEndHandler("link",this,&NodeHandler::endLink);
addStartHandler("label",this,&NodeHandler::startLabel);
addEndHandler("label",this,&NodeHandler::endLabel);
addStartHandler("childnode",this,&NodeHandler::startChildNode);
m_children.setAutoDelete(TRUE);
}
NodeHandler::~NodeHandler()
{
}
void NodeHandler::startNode(const QXmlAttributes &attrib)
{
debug(2,"startNode\n");
m_parent->setDelegate(this);
m_id = attrib.value("id");
}
void NodeHandler::endNode()
{
debug(2,"endNode\n");
m_parent->setDelegate(0);
}
void NodeHandler::startLink(const QXmlAttributes &attrib)
{
m_link = attrib.value("refid");
}
void NodeHandler::endLink()
{
}
void NodeHandler::startLabel(const QXmlAttributes &/*attrib*/)
{
m_curString="";
}
void NodeHandler::endLabel()
{
m_label = m_curString;
}
void NodeHandler::startChildNode(const QXmlAttributes &attrib)
{
ChildNodeHandler *cnh = new ChildNodeHandler(this,m_graph);
cnh->startChildNode(attrib);
m_children.append(cnh);
}
IChildNodeIterator *NodeHandler::children() const
{
return new ChildNodeIterator(*this);
}
//------------------------------------------------------------------------
ChildNodeHandler::ChildNodeHandler(IBaseHandler *parent,GraphHandler *gh)
: m_parent(parent), m_graph(gh)
{
addEndHandler("childnode",this,&ChildNodeHandler::endChildNode);
addStartHandler("edgelabel",this,&ChildNodeHandler::startEdgeLabel);
m_edgeLabels.setAutoDelete(TRUE);
}
ChildNodeHandler::~ChildNodeHandler()
{
}
void ChildNodeHandler::startChildNode(const QXmlAttributes &attrib)
{
debug(2,"startChildNode\n");
m_id = attrib.value("refid");
m_relationString = attrib.value("relation");
m_relation = s_edgeRelationMapper->stringToNodeRelation(m_relationString);
m_parent->setDelegate(this);
}
void ChildNodeHandler::endChildNode()
{
debug(2,"endChildNode\n");
m_parent->setDelegate(0);
}
void ChildNodeHandler::startEdgeLabel(const QXmlAttributes &attrib)
{
EdgeLabelHandler *elh = new EdgeLabelHandler(this);
elh->startEdgeLabel(attrib);
m_edgeLabels.append(elh);
}
IEdgeLabelIterator *ChildNodeHandler::edgeLabels() const
{
return new EdgeLabelIterator(*this);
}
INode *ChildNodeHandler::node() const
{
return m_graph->getNodeById(m_id);
}
//-----------------------------------------------------------------------
EdgeLabelHandler::EdgeLabelHandler(IBaseHandler *parent)
: m_parent(parent)
{
addEndHandler("edgelabel",this,&EdgeLabelHandler::endEdgeLabel);
}
EdgeLabelHandler::~EdgeLabelHandler()
{
}
void EdgeLabelHandler::startEdgeLabel(const QXmlAttributes &)
{
m_parent->setDelegate(this);
m_curString="";
}
void EdgeLabelHandler::endEdgeLabel()
{
m_label=m_curString;
m_parent->setDelegate(0);
}

View File

@ -0,0 +1,154 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef _GRAPHHANDLER_H
#define _GRAPHHANDLER_H
#include "stringimpl.h"
#include "doxmlintf.h"
#include "basehandler.h"
#include "baseiterator.h"
class NodeHandler;
class ChildNodeHandler;
class EdgeLabelHandler;
class GraphHandler : public IGraph, public BaseHandler<GraphHandler>
{
friend class NodeIterator;
public:
GraphHandler(IBaseHandler *parent,const char *endTag);
virtual ~GraphHandler();
void startGraph(const QXmlAttributes &attrib);
void endGraph();
void startNode(const QXmlAttributes &attrib);
NodeHandler *getNodeById(const QString &id) const;
// IGraph
virtual INodeIterator *nodes() const;
private:
IBaseHandler *m_parent;
QList<NodeHandler> m_nodes;
QDict<NodeHandler> *m_nodeDict;
};
//----------------------------------------------------------------------
class NodeHandler : public INode, public BaseHandler<NodeHandler>
{
friend class ChildNodeIterator;
public:
NodeHandler(GraphHandler *gh);
virtual ~NodeHandler();
void startNode(const QXmlAttributes &attrib);
void endNode();
void startLabel(const QXmlAttributes &attrib);
void endLabel();
void startLink(const QXmlAttributes &attrib);
void endLink();
void startChildNode(const QXmlAttributes &attrib);
// INode
virtual const IString *id() const { return &m_id; }
virtual const IString *label() const { return &m_label; }
virtual const IString *linkId() const { return &m_link; }
virtual IChildNodeIterator *children() const;
private:
IBaseHandler *m_parent;
StringImpl m_id;
StringImpl m_label;
StringImpl m_link;
QList<ChildNodeHandler> m_children;
GraphHandler *m_graph;
};
class NodeIterator : public BaseIterator<INodeIterator,INode,NodeHandler>
{
public:
NodeIterator(const GraphHandler &handler) :
BaseIterator<INodeIterator,INode,NodeHandler>(handler.m_nodes) {}
};
//----------------------------------------------------------------------
class ChildNodeHandler : public IChildNode, public BaseHandler<ChildNodeHandler>
{
friend class EdgeLabelIterator;
public:
ChildNodeHandler(IBaseHandler *parent,GraphHandler *gh);
virtual ~ChildNodeHandler();
void startChildNode(const QXmlAttributes &attrib);
void endChildNode();
void startEdgeLabel(const QXmlAttributes &attrib);
// IChildNode
virtual INode *node() const;
virtual NodeRelation relation() const { return m_relation; }
virtual const IString * relationString() const { return &m_relationString; }
virtual IEdgeLabelIterator *edgeLabels() const;
private:
IBaseHandler *m_parent;
QString m_id;
NodeRelation m_relation;
StringImpl m_relationString;
QList<EdgeLabelHandler> m_edgeLabels;
GraphHandler *m_graph;
};
class ChildNodeIterator : public BaseIterator<IChildNodeIterator,IChildNode,ChildNodeHandler>
{
public:
ChildNodeIterator(const NodeHandler &handler) :
BaseIterator<IChildNodeIterator,IChildNode,ChildNodeHandler>(handler.m_children) {}
};
//----------------------------------------------------------------------
class EdgeLabelHandler : public IEdgeLabel, public BaseHandler<EdgeLabelHandler>
{
friend class EdgeLabelIterator;
public:
EdgeLabelHandler(IBaseHandler *parent);
virtual ~EdgeLabelHandler();
void startEdgeLabel(const QXmlAttributes &attrib);
void endEdgeLabel();
// IEdgeLabel
virtual const IString *label() const { return &m_label; }
private:
IBaseHandler *m_parent;
StringImpl m_label;
};
class EdgeLabelIterator : public BaseIterator<IEdgeLabelIterator,IEdgeLabel,EdgeLabelHandler>
{
public:
EdgeLabelIterator(const ChildNodeHandler &handler) :
BaseIterator<IEdgeLabelIterator,IEdgeLabel,EdgeLabelHandler>(handler.m_edgeLabels) {}
};
void graphhandler_init();
void graphhandler_exit();
#endif

View File

@ -0,0 +1,133 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include "linkedtexthandler.h"
#include "debug.h"
#include <doxmlintf.h>
#include "stringimpl.h"
class LT_Text : public LinkedTextImpl, public ILT_Text
{
public:
LT_Text(const QString &text) : m_text(text) {}
virtual ~LT_Text() {}
// ILT_Text
virtual const IString *text() const { return &m_text; }
virtual Kind kind() const { return LinkedTextImpl::Kind_Text; }
private:
StringImpl m_text;
};
class LT_Ref : public LinkedTextImpl, public ILT_Ref
{
public:
LT_Ref() {}
virtual ~LT_Ref() {}
void setRefId(const QString &refId) { m_refId=refId; }
void setText(const QString &text) { m_text=text; }
void setExtId(const QString &extId) { m_extId=extId; }
void setTargetKind(TargetKind k) { m_targetKind=k; }
// ILT_Ref
virtual const IString *text() const { return &m_text; }
virtual const IString * id() const { return &m_refId; }
virtual TargetKind targetKind() const { return m_targetKind; }
virtual const IString *external() const { return &m_extId; }
virtual Kind kind() const { return LinkedTextImpl::Kind_Ref; }
private:
StringImpl m_refId;
StringImpl m_extId;
StringImpl m_text;
TargetKind m_targetKind = TargetKind::Member;
};
LinkedTextHandler::LinkedTextHandler(IBaseHandler *parent,
QList<LinkedTextImpl> &children
)
: m_parent(parent), m_children(children)
{
addStartHandler("ref",this,&LinkedTextHandler::startRef);
addEndHandler("ref",this,&LinkedTextHandler::endRef);
m_children.setAutoDelete(TRUE);
m_ref=0;
}
LinkedTextHandler::~LinkedTextHandler()
{
}
void LinkedTextHandler::start(const char *endTag)
{
addEndHandler(endTag,this,&LinkedTextHandler::end);
m_parent->setDelegate(this);
m_curString="";
}
void LinkedTextHandler::end()
{
if (!m_curString.isEmpty())
{
m_children.append(new LT_Text(m_curString));
debug(2,"LinkedTextHandler: add text '%s'\n",m_curString.data());
m_curString="";
}
m_parent->setDelegate(0);
}
void LinkedTextHandler::startRef(const QXmlAttributes& attrib)
{
if (!m_curString.isEmpty())
{
m_children.append(new LT_Text(m_curString));
debug(2,"LinkedTextHandler: add text '%s'\n",m_curString.data());
m_curString="";
}
ASSERT(m_ref==0);
m_ref = new LT_Ref;
m_ref->setRefId(attrib.value("refid"));
m_ref->setExtId(attrib.value("external"));
ASSERT(attrib.value("kindref")=="compound" || attrib.value("kindref")=="member");
m_ref->setTargetKind(attrib.value("kindref")=="compound" ? ILT_Ref::Compound : ILT_Ref::Member);
}
void LinkedTextHandler::endRef()
{
m_ref->setText(m_curString);
m_children.append(m_ref);
debug(2,"LinkedTextHandler: add ref '%s'\n",m_ref->text()->latin1());
m_ref=0;
}
QString LinkedTextHandler::toString(const QList<LinkedTextImpl> &list)
{
QListIterator<LinkedTextImpl> li(list);
QString result;
LinkedTextImpl *lt;
for (li.toFirst();(lt=li.current());++li)
{
switch(lt->kind())
{
case ILinkedText::Kind_Text:
result+=dynamic_cast<ILT_Text*>(lt)->text()->latin1();
break;
case ILinkedText::Kind_Ref:
result+=dynamic_cast<ILT_Ref *>(lt)->text()->latin1();
break;
}
}
return result;
}

View File

@ -0,0 +1,54 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef LINKEDTEXTHANDLER_H
#define LINKEDTEXTHANDLER_H
#include "baseiterator.h"
#include "basehandler.h"
class LT_Ref;
class LinkedTextImpl : public ILinkedText
{
public:
virtual ~LinkedTextImpl() {}
};
class LinkedTextHandler : public BaseHandler<LinkedTextHandler>
{
public:
LinkedTextHandler(IBaseHandler *parent,QList<LinkedTextImpl> &children);
virtual ~LinkedTextHandler();
virtual void start(const char *endTag);
virtual void end();
virtual void startRef(const QXmlAttributes& attrib);
virtual void endRef();
static QString toString(const QList<LinkedTextImpl> &list);
// ILinkedText
private:
IBaseHandler *m_parent;
QList<LinkedTextImpl> &m_children;
LT_Ref *m_ref;
};
class LinkedTextIterator : public BaseIterator<ILinkedTextIterator,ILinkedText,LinkedTextImpl>
{
public:
LinkedTextIterator(const QList<LinkedTextImpl> &list) :
BaseIterator<ILinkedTextIterator,ILinkedText,LinkedTextImpl>(list) {}
};
#endif

View File

@ -0,0 +1,77 @@
#include "loamhandler.h"
#include "memberhandler.h"
#include "linkedtexthandler.h"
#include "paramhandler.h"
ListOfAllMembersHandler::ListOfAllMembersHandler(IBaseHandler *parent) : m_parent(parent)
{
m_members.setAutoDelete(TRUE);
addStartHandler("member",this,&ListOfAllMembersHandler::startMember);
addStartHandler("name",this,&ListOfAllMembersHandler::startName);
addEndHandler("name",this,&ListOfAllMembersHandler::endName);
addStartHandler("scope",this,&ListOfAllMembersHandler::startScope);
addEndHandler("scope",this,&ListOfAllMembersHandler::endScope);
addEndHandler("listofallmembers",this,&ListOfAllMembersHandler::endListOfAllMembers);
}
void ListOfAllMembersHandler::initialize(MainHandler *mh)
{
QListIterator<MemberReference> mli(m_members);
MemberReference *mr;
for (;(mr=mli.current());++mli)
{
mr->initialize(mh);
}
}
void ListOfAllMembersHandler::startMember(const QXmlAttributes& attrib)
{
MemberReference *mr = new MemberReference;
mr->m_memId = attrib.value("refid");
mr->m_virtualness = attrib.value("virt");
mr->m_protection = attrib.value("prot");
mr->m_ambiguityScope = attrib.value("ambiguityscope");
m_members.append(new MemberReference);
}
void ListOfAllMembersHandler::startName(const QXmlAttributes&)
{
m_curString="";
}
void ListOfAllMembersHandler::endName()
{
ASSERT(m_members.getLast());
m_members.getLast()->m_name = m_curString;
}
void ListOfAllMembersHandler::startScope(const QXmlAttributes&)
{
m_curString="";
}
void ListOfAllMembersHandler::endScope()
{
ASSERT(m_members.getLast());
m_members.getLast()->m_scope = m_curString;
}
void ListOfAllMembersHandler::startListOfAllMembers(const QXmlAttributes& /*attrib*/)
{
m_parent->setDelegate(this);
debug(2,"listofallmembers start\n");
}
void ListOfAllMembersHandler::endListOfAllMembers()
{
m_parent->setDelegate(0);
debug(2,"listofallmembers end\n");
}
IMemberReferenceIterator *ListOfAllMembersHandler::members() const
{
return new MemberReferenceIterator(m_members);
}

View File

@ -0,0 +1,52 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef _LOAMHANDLER_H
#define _LOAMHANDLER_H
#include <qstring.h>
#include <qlist.h>
#include <doxmlintf.h>
#include "basehandler.h"
class MainHandler;
class MemberReference;
class ListOfAllMembersHandler : public BaseHandler<ListOfAllMembersHandler>
{
public:
virtual void startMember(const QXmlAttributes& attrib);
virtual void startName(const QXmlAttributes& attrib);
virtual void endName();
virtual void startScope(const QXmlAttributes& attrib);
virtual void endScope();
virtual void startListOfAllMembers(const QXmlAttributes& attrib);
virtual void endListOfAllMembers();
ListOfAllMembersHandler(IBaseHandler *parent);
virtual ~ListOfAllMembersHandler() {}
void initialize(MainHandler *mh);
virtual IMemberReferenceIterator *members() const;
protected:
IBaseHandler *m_parent;
QList<MemberReference> m_members;
};
#endif

View File

@ -0,0 +1,301 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include <qxml.h>
#include "mainhandler.h"
#include "compoundhandler.h"
#include "sectionhandler.h"
#include "graphhandler.h"
#include "dochandler.h"
#include "memberhandler.h"
#include "linkedtexthandler.h"
#include "paramhandler.h"
#include "debug.h"
class ErrorHandler : public QXmlErrorHandler
{
public:
virtual ~ErrorHandler() {}
bool warning( const QXmlParseException & )
{
return FALSE;
}
bool error( const QXmlParseException & )
{
return FALSE;
}
bool fatalError( const QXmlParseException &exception )
{
debug(1,"Fatal error at line %d column %d: %s\n",
exception.lineNumber(),exception.columnNumber(),
exception.message().data());
return FALSE;
}
QString errorString() { return ""; }
private:
QString errorMsg;
};
//--------------------------------------------------------------------------
class CompoundEntryIterator : public ICompoundIterator,
public QListIterator<CompoundEntry>
{
public:
CompoundEntryIterator(const MainHandler *m,const QList<CompoundEntry> &list) :
QListIterator<CompoundEntry>(list), m_mainHandler(m) {}
virtual ~CompoundEntryIterator() {}
virtual void toFirst()
{
QListIterator<CompoundEntry>::toFirst();
}
virtual void toLast()
{
QListIterator<CompoundEntry>::toLast();
}
virtual void toNext()
{
QListIterator<CompoundEntry>::operator++();
}
virtual void toPrev()
{
QListIterator<CompoundEntry>::operator--();
}
virtual ICompound *current() const
{
CompoundEntry *ch = QListIterator<CompoundEntry>::current();
return ch ? m_mainHandler->compoundById(ch->id.utf8()) : 0;
}
virtual void release()
{ delete this; }
private:
const MainHandler *m_mainHandler;
};
//--------------------------------------------------------------------------
MainHandler::MainHandler() : m_compoundDict(2999), m_compoundNameDict(2999),
m_memberDict(12251), m_memberNameDict(12251),
m_compoundsLoaded(1009)
{
m_compounds.setAutoDelete(TRUE);
m_memberNameDict.setAutoDelete(TRUE);
addStartHandler("doxygenindex");
addEndHandler("doxygenindex");
addStartHandler("compound",this,&MainHandler::startCompound);
addEndHandler("compound");
addStartHandler("member",this,&MainHandler::startMember);
addEndHandler("member",this,&MainHandler::endMember);
addStartHandler("name",this,&MainHandler::startName);
addEndHandler("name",this,&MainHandler::endName);
m_curCompound = 0;
m_insideMember = FALSE;
}
MainHandler::~MainHandler()
{
debug(2,"MainHandler::~MainHandler()\n");
}
void MainHandler::startCompound(const QXmlAttributes& attrib)
{
m_curCompound = new CompoundEntry(257);
m_curCompound->id = attrib.value("refid");
m_compounds.append(m_curCompound);
m_compoundDict.insert(m_curCompound->id.utf8(),m_curCompound);
}
void MainHandler::startName(const QXmlAttributes& /*attrib*/)
{
m_curString = "";
}
void MainHandler::endName()
{
if (m_insideMember)
{
m_curMember->name = m_curString;
}
else
{
m_curCompound->name = m_curString;
m_compoundNameDict.insert(m_curString.utf8(),m_curCompound);
}
}
void MainHandler::startMember(const QXmlAttributes& attrib)
{
m_insideMember = TRUE;
m_curMember = new MemberEntry;
m_curMember->id = attrib.value("refid");
m_curMember->compound = m_curCompound;
m_memberDict.insert(m_curMember->id.utf8(),m_curMember);
}
void MainHandler::endMember()
{
m_curCompound->memberDict.insert(m_curMember->name.utf8(),m_curMember);
QList<CompoundEntry> *cel=0;
if ((cel=m_memberNameDict.find(m_curMember->name.utf8()))==0)
{
cel = new QList<CompoundEntry>;
m_memberNameDict.insert(m_curMember->name.utf8(),cel);
}
cel->append(m_curCompound);
m_insideMember = FALSE;
}
void MainHandler::setDebugLevel(int level)
{
::setDebugLevel(level);
}
void MainHandler::dump()
{
QListIterator<CompoundEntry> cli(m_compounds);
CompoundEntry *ce;
for (cli.toFirst();(ce=cli.current());++cli)
{
debug(2,"compound id='%s' name='%s'\n",ce->id.data(),ce->name.data());
QDictIterator<MemberEntry> mdi(ce->memberDict);
MemberEntry *me;
for (mdi.toFirst();(me=mdi.current());++mdi)
{
debug(2," member id='%s' name='%s'\n",me->id.data(),me->name.data());
}
}
}
bool MainHandler::readXMLDir(const char * xmlDirName)
{
m_xmlDirName = xmlDirName;
QString xmlFileName=m_xmlDirName+"/index.xml";
QFile xmlFile(xmlFileName);
//printf("Trying %s xmlFile.exists()=%d isReadable()=%d\n",
// xmlFileName.data(),xmlFile.exists(),xmlFile.isReadable());
if (xmlFile.exists())
{
ErrorHandler errorHandler;
QXmlInputSource source( xmlFile );
QXmlSimpleReader reader;
reader.setContentHandler( this );
reader.setErrorHandler( &errorHandler );
reader.parse( source );
dump();
return TRUE;
}
return FALSE;
}
ICompoundIterator *MainHandler::compounds() const
{
return new CompoundEntryIterator(this,m_compounds);
}
ICompound *MainHandler::compoundById(const char *id) const
{
QString ids = id;
if (ids.isEmpty()) return 0;
CompoundHandler *ch = m_compoundsLoaded[ids.utf8()];
if (ch) // compound already in memory
{
ch->addref(); // returning alias -> increase reference counter
return ch->toICompound();
}
CompoundEntry *ce = m_compoundDict.find(ids.utf8());
if (ce==0) return 0; // id not found
// create and load a new compound
ch = new CompoundHandler(m_xmlDirName);
if (!ch->parseXML(id))
{
// compound could not be initialized.
delete ch;
return 0;
}
// we disregard the constness here, because the object stays conceptually
// unchanged.
MainHandler *that = (MainHandler *)this;
ch->initialize(that);
//printf("loading compound %s in memory\n",id);
that->m_compoundsLoaded.insert(id,ch);
return ch->toICompound();
}
void MainHandler::unloadCompound(CompoundHandler *ch)
{
//printf("unloading compound %s from memory\n",ch->id()->latin1());
bool result = m_compoundsLoaded.remove(ch->id()->latin1());
if (!result) debug(1,"Failed to unload component!\n");
}
ICompound *MainHandler::compoundByName(const char *name) const
{
QString nameStr = name;
if (nameStr.isEmpty()) return 0;
CompoundEntry *ce = m_compoundNameDict[name];
if (ce==0) return 0; // name not found
return compoundById(ce->id.utf8());
}
ICompound *MainHandler::memberById(const char *id) const
{
QString ids = id;
if (ids.isEmpty()) return 0;
MemberEntry *me = m_memberDict[id];
if (me==0) return 0; // id not found
return compoundById(me->compound->id.utf8());
}
ICompoundIterator *MainHandler::memberByName(const char *name) const
{
QString nameStr = name;
if (nameStr.isEmpty()) return 0;
QList<CompoundEntry> *cel = m_memberNameDict[name];
if (cel==0) return 0; // name not found
return new CompoundEntryIterator(this,*cel);
}
IDoxygen *createObjectModel()
{
compoundhandler_init();
sectionhandler_init();
memberhandler_init();
dochandler_init();
graphhandler_init();
return new MainHandler;
}
void MainHandler::release()
{
//printf("MainHandler::release()\n");
QDictIterator<CompoundHandler> chi(m_compoundsLoaded);
CompoundHandler *ch;
for (chi.toFirst();(ch=chi.current());++chi)
{
debug(1,"Compound %s not released\n",ch->name()->latin1());
}
graphhandler_exit();
dochandler_exit();
memberhandler_exit();
sectionhandler_exit();
compoundhandler_exit();
delete this;
}

View File

@ -0,0 +1,82 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef _MAINHANDLER_H
#define _MAINHANDLER_H
#include <qlist.h>
#include <doxmlintf.h>
#include "basehandler.h"
class CompoundHandler;
struct CompoundEntry;
struct IndexEntry
{
QString id;
QString name;
};
struct MemberEntry : public IndexEntry
{
CompoundEntry *compound;
};
struct CompoundEntry : public IndexEntry
{
CompoundEntry(int size) : memberDict(size)
{ memberDict.setAutoDelete(TRUE); }
QDict<MemberEntry> memberDict;
};
class MainHandler : public IDoxygen, public BaseHandler<MainHandler>
{
public:
virtual void startCompound(const QXmlAttributes& attrib);
virtual void startMember(const QXmlAttributes& attrib);
virtual void endMember();
virtual void startName(const QXmlAttributes& attrib);
virtual void endName();
MainHandler();
virtual ~MainHandler();
// IDoxygen
ICompoundIterator *compounds() const;
ICompound *compoundById(const char *id) const;
virtual ICompound *compoundByName(const char *name) const;
virtual ICompound *memberById(const char *id) const;
virtual ICompoundIterator *memberByName(const char *name) const;
virtual void release();
void setDebugLevel(int level);
bool readXMLDir(const char *dirName);
void dump();
void unloadCompound(CompoundHandler *ch);
private:
CompoundEntry *m_curCompound;
MemberEntry *m_curMember;
QList<CompoundEntry> m_compounds;
QDict<CompoundEntry> m_compoundDict;
QDict<CompoundEntry> m_compoundNameDict;
QDict<MemberEntry> m_memberDict;
QDict<QList<CompoundEntry> > m_memberNameDict;
QString m_xmlDirName;
QDict<CompoundHandler> m_compoundsLoaded;
bool m_insideMember;
};
#endif

View File

@ -0,0 +1,600 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include "memberhandler.h"
#include "sectionhandler.h"
#include "dochandler.h"
#include "mainhandler.h"
#include "linkedtexthandler.h"
#include "paramhandler.h"
#include "compoundhandler.h"
#include "debug.h"
//------------------------------------------------------------------------------
class MemberTypeMap
{
public:
MemberTypeMap()
{
m_map.setAutoDelete(TRUE);
m_map.insert("define",new int(IMember::Define));
m_map.insert("property",new int(IMember::Property));
m_map.insert("variable",new int(IMember::Variable));
m_map.insert("typedef",new int(IMember::Typedef));
m_map.insert("enum",new int(IMember::Enum));
m_map.insert("function",new int(IMember::Function));
m_map.insert("signal",new int(IMember::Signal));
m_map.insert("prototype",new int(IMember::Prototype));
m_map.insert("friend",new int(IMember::Friend));
m_map.insert("dcop",new int(IMember::DCOP));
m_map.insert("slot",new int(IMember::Slot));
m_map.insert("enumvalue",new int(IMember::EnumValue));
}
IMember::MemberKind map(const QString &s)
{
int *val = m_map.find(s.utf8());
if (val==0)
{
debug(1,"Warning: '%s' is an invalid member type\n",s.data());
return IMember::Invalid;
}
else return (IMember::MemberKind)*val;
}
private:
QDict<int> m_map;
};
static MemberTypeMap *s_typeMap;
void memberhandler_init()
{
s_typeMap = new MemberTypeMap;
}
void memberhandler_exit()
{
delete s_typeMap;
}
//------------------------------------------------------------------------------
void MemberReference::initialize(MainHandler *mh)
{
m_mainHandler = mh;
}
IMember *MemberReference::member() const
{
//return m_mainHandler->memberById(m_memId);
return 0;
}
//------------------------------------------------------------------------------
#if 0
EnumValueHandler::EnumValueHandler(IBaseHandler *parent) :
m_parent(parent), m_brief(0), m_detailed(0), m_linkedTextHandler(0)
{
addEndHandler("enumvalue",this,&EnumValueHandler::endEnumValue);
addStartHandler("name",this,&EnumValueHandler::startName);
addEndHandler("name",this,&EnumValueHandler::endName);
addStartHandler("initializer",this,&EnumValueHandler::startInitializer);
addStartHandler("briefdescription",this,&EnumValueHandler::startBriefDesc);
addStartHandler("detaileddescription",this,&EnumValueHandler::startDetailedDesc);
m_initializer.setAutoDelete(TRUE);
}
EnumValueHandler::~EnumValueHandler()
{
delete m_brief;
delete m_detailed;
delete m_linkedTextHandler;
}
void EnumValueHandler::startEnumValue(const QXmlAttributes& /*attrib*/)
{
m_parent->setDelegate(this);
}
void EnumValueHandler::endEnumValue()
{
m_parent->setDelegate(0);
}
void EnumValueHandler::startName(const QXmlAttributes& /*attrib*/)
{
m_curString="";
}
void EnumValueHandler::endName()
{
m_name = m_curString;
}
void EnumValueHandler::startInitializer(const QXmlAttributes& /*attrib*/)
{
delete m_linkedTextHandler;
m_linkedTextHandler = new LinkedTextHandler(this,m_initializer);
m_linkedTextHandler->start("initializer");
}
void EnumValueHandler::startBriefDesc(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_brief = docHandler;
}
void EnumValueHandler::startDetailedDesc(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_detailed = docHandler;
}
#endif
//------------------------------------------------------------------------------
MemberHandler::MemberHandler(IBaseHandler *parent)
: m_brief(0), m_detailed(0), m_inbody(0),
m_compound(0), m_section(0), m_parent(parent)
{
//printf("MemberHandler::MemberHandler() %p\n",this);
addEndHandler("memberdef",this,&MemberHandler::endMember);
addStartHandler("templateparamlist",this,&MemberHandler::startTemplateParamList);
addEndHandler("templateparamlist",this,&MemberHandler::endTemplateParamList);
addStartHandler("type",this,&MemberHandler::startType);
addStartHandler("definition",this,&MemberHandler::startDefinition);
addEndHandler("definition",this,&MemberHandler::endDefinition);
addStartHandler("argsstring",this,&MemberHandler::startArgsString);
addEndHandler("argsstring",this,&MemberHandler::endArgsString);
addStartHandler("name",this,&MemberHandler::startName);
addEndHandler("name",this,&MemberHandler::endName);
addStartHandler("read",this,&MemberHandler::startRead);
addEndHandler("read",this,&MemberHandler::endRead);
addStartHandler("write",this,&MemberHandler::startWrite);
addEndHandler("write",this,&MemberHandler::endWrite);
addStartHandler("reimplements",this,&MemberHandler::startReimplements);
addEndHandler("reimplements",this,&MemberHandler::endReimplements);
addStartHandler("reimplementedby",this,&MemberHandler::startReimplementedBy);
addEndHandler("reimplementedby",this,&MemberHandler::endReimplementedBy);
addStartHandler("param",this,&MemberHandler::startParam);
addStartHandler("enumvalue",this,&MemberHandler::startEnumValue2);
addEndHandler("enumvalue",this,&MemberHandler::endMember);
addStartHandler("initializer",this,&MemberHandler::startInitializer);
addStartHandler("exceptions",this,&MemberHandler::startException);
addStartHandler("briefdescription",this,&MemberHandler::startBriefDesc);
addStartHandler("detaileddescription",this,&MemberHandler::startDetailedDesc);
addStartHandler("inbodydescription",this,&MemberHandler::startInbodyDesc);
addStartHandler("location",this,&MemberHandler::startLocation);
addEndHandler("location");
addStartHandler("references",this,&MemberHandler::startReferences);
addEndHandler("references",this,&MemberHandler::endReferences);
addStartHandler("referencedby",this,&MemberHandler::startReferencedBy);
addEndHandler("referencedby",this,&MemberHandler::endReferencedBy);
m_type.setAutoDelete(TRUE);
m_initializer.setAutoDelete(TRUE);
m_exception.setAutoDelete(TRUE);
m_params.setAutoDelete(TRUE);
m_references.setAutoDelete(TRUE);
m_referencedBy.setAutoDelete(TRUE);
m_reimplements = 0;
m_reimplementedBy.setAutoDelete(TRUE);
m_enumValues.setAutoDelete(TRUE);
m_linkedTextHandler = 0;
m_defLine=0;
m_bodyStart=0;
m_bodyEnd=0;
m_insideTemplateParamList=FALSE;
m_hasTemplateParamList=FALSE;
}
MemberHandler::~MemberHandler()
{
debug(2,"MemberHandler::~MemberHandler() %p\n",this);
delete m_brief;
delete m_detailed;
delete m_inbody;
delete m_linkedTextHandler;
delete m_reimplements;
}
void MemberHandler::startMember(const QXmlAttributes& attrib)
{
m_parent->setDelegate(this);
m_kindString = attrib.value("kind");
//printf("startMember kindString='%s'\n",m_kindString.data());
m_kind = s_typeMap->map(m_kindString);
m_id = attrib.value("id");
m_protection = attrib.value("prot");
m_isStatic = attrib.value("static")=="yes";
m_isConst = attrib.value("const")=="yes";
m_isExplicit = attrib.value("explicit")=="yes";
m_isInline = attrib.value("inline")=="yes";
m_virtualness = attrib.value("virt");
m_isVolatile = attrib.value("volatile")=="yes";
m_isMutable = attrib.value("mutable")=="yes";
m_isReadable = attrib.value("readable")=="yes";
m_isWritable = attrib.value("writable")=="yes";
debug(2,"member kind='%s' id='%s' prot='%s' virt='%s'\n",
m_kindString.data(),m_id.data(),m_protection.data(),m_virtualness.data());
}
void MemberHandler::startEnumValue(const QXmlAttributes& attrib)
{
m_parent->setDelegate(this);
m_kindString = "enumvalue";
//printf("startEnumValue kindString='%s'\n",m_kindString.data());
m_kind = s_typeMap->map(m_kindString);
m_id = attrib.value("id");
m_protection = attrib.value("prot");
m_isStatic = FALSE;
m_isConst = FALSE;
m_isExplicit = FALSE;
m_isInline = FALSE;
m_virtualness = "non-virtual";
m_isVolatile = FALSE;
m_isMutable = FALSE;
m_isReadable = FALSE;
m_isWritable = FALSE;
debug(2,"member kind='%s' id='%s' prot='%s' virt='%s'\n",
m_kindString.data(),m_id.data(),m_protection.data(),m_virtualness.data());
}
void MemberHandler::startEnumValue2(const QXmlAttributes& attrib)
{
MemberHandler *mh = new MemberHandler(this);
mh->startEnumValue(attrib);
m_enumValues.append(mh);
}
void MemberHandler::startBriefDesc(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_brief = docHandler;
}
void MemberHandler::startDetailedDesc(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_detailed = docHandler;
}
void MemberHandler::startInbodyDesc(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_inbody = docHandler;
}
void MemberHandler::startLocation(const QXmlAttributes& attrib)
{
m_defFile = attrib.value("file");
m_bodyFile = attrib.value("bodyfile");
QString s;
s = attrib.value("line");
if (!s.isEmpty()) m_defLine=s.toInt();
s = attrib.value("bodystart");
if (!s.isEmpty()) m_bodyStart=s.toInt();
s = attrib.value("bodyend");
if (!s.isEmpty()) m_bodyEnd=s.toInt();
}
void MemberHandler::startReferences(const QXmlAttributes& attrib)
{
MemberReference *mr = new MemberReference;
mr->m_memId = attrib.value("refid");
m_references.append(mr);
m_curString="";
}
void MemberHandler::endReferences()
{
m_references.getLast()->m_name = m_curString;
}
void MemberHandler::startReferencedBy(const QXmlAttributes& attrib)
{
MemberReference *mr = new MemberReference;
mr->m_memId = attrib.value("refid");
m_referencedBy.append(mr);
m_curString="";
}
void MemberHandler::endReferencedBy()
{
m_referencedBy.getLast()->m_name = m_curString;
}
void MemberHandler::startReimplements(const QXmlAttributes& attrib)
{
m_reimplements = new MemberReference;
m_reimplements->m_memId = attrib.value("refid");
m_curString="";
}
void MemberHandler::endReimplements()
{
m_reimplements->m_name = m_curString;
}
void MemberHandler::startReimplementedBy(const QXmlAttributes& attrib)
{
MemberReference *mr = new MemberReference;
mr->m_memId = attrib.value("refid");
m_reimplementedBy.append(mr);
m_curString="";
}
void MemberHandler::endReimplementedBy()
{
m_reimplementedBy.getLast()->m_name = m_curString;
}
void MemberHandler::endMember()
{
m_parent->setDelegate(0);
}
void MemberHandler::startType(const QXmlAttributes &)
{
debug(2,"startType!\n");
delete m_linkedTextHandler;
m_linkedTextHandler = new LinkedTextHandler(this,m_type);
m_linkedTextHandler->start("type");
}
void MemberHandler::startInitializer(const QXmlAttributes &)
{
debug(2,"startInitializer!\n");
delete m_linkedTextHandler;
m_linkedTextHandler = new LinkedTextHandler(this,m_initializer);
m_linkedTextHandler->start("initializer");
}
void MemberHandler::startException(const QXmlAttributes &)
{
debug(2,"startException!\n");
delete m_linkedTextHandler;
m_linkedTextHandler = new LinkedTextHandler(this,m_exception);
m_linkedTextHandler->start("exceptions");
}
void MemberHandler::startName(const QXmlAttributes &)
{
m_curString="";
}
void MemberHandler::endName()
{
m_name = m_curString.stripWhiteSpace();
debug(2,"member name='%s'\n",m_name.data());
}
void MemberHandler::startRead(const QXmlAttributes &)
{
m_curString="";
}
void MemberHandler::endRead()
{
m_read = m_curString.stripWhiteSpace();
debug(2,"member read='%s'\n",m_read.data());
}
void MemberHandler::startWrite(const QXmlAttributes &)
{
m_curString="";
}
void MemberHandler::endWrite()
{
m_write = m_curString.stripWhiteSpace();
debug(2,"member write='%s'\n",m_write.data());
}
void MemberHandler::startDefinition(const QXmlAttributes&)
{
m_curString="";
}
void MemberHandler::endDefinition()
{
m_definition = m_curString.stripWhiteSpace();
debug(2,"definition=%s\n",m_definition.data());
}
void MemberHandler::startArgsString(const QXmlAttributes&)
{
m_curString="";
}
void MemberHandler::endArgsString()
{
m_argsstring = m_curString.stripWhiteSpace();
debug(2,"argstring=%s\n",m_argsstring.data());
}
void MemberHandler::startParam(const QXmlAttributes& attrib)
{
ParamHandler *paramHandler = new ParamHandler(this);
paramHandler->startParam(attrib);
if (m_insideTemplateParamList)
{
m_templateParams.append(paramHandler);
}
else
{
m_params.append(paramHandler);
}
}
void MemberHandler::startTemplateParamList(const QXmlAttributes&)
{
m_insideTemplateParamList = TRUE;
m_hasTemplateParamList = TRUE;
}
void MemberHandler::endTemplateParamList()
{
m_insideTemplateParamList = FALSE;
}
void MemberHandler::initialize(MainHandler *mh)
{
{
QListIterator<MemberReference> mli(m_references);
MemberReference *mr;
for (;(mr=mli.current());++mli)
{
mr->initialize(mh);
}
}
{
QListIterator<MemberReference> mli(m_referencedBy);
MemberReference *mr;
for (;(mr=mli.current());++mli)
{
mr->initialize(mh);
}
}
{
QListIterator<MemberReference> mli(m_reimplementedBy);
MemberReference *mr;
for (;(mr=mli.current());++mli)
{
mr->initialize(mh);
}
}
if (m_reimplements) m_reimplements->initialize(mh);
}
void MemberHandler::setCompoundHandler(CompoundHandler *c)
{
m_compound = c;
}
ICompound *MemberHandler::compound() const
{
m_compound->addref();
return m_compound->toICompound();
}
void MemberHandler::setSectionHandler(SectionHandler *c)
{
m_section = c;
}
ISection *MemberHandler::section() const
{
return m_section;
}
IMemberIterator *MemberHandler::enumValues() const
{
return new MemberIterator(m_enumValues);
}
ILinkedTextIterator *MemberHandler::type() const
{
return new LinkedTextIterator(m_type);
}
const IString *MemberHandler::typeString() const
{
MemberHandler *that = (MemberHandler *)this;
that->m_typeString = LinkedTextHandler::toString(m_type);
return &m_typeString;
}
IParamIterator *MemberHandler::parameters() const
{
return new ParamIterator(m_params);
}
IParamIterator *MemberHandler::templateParameters() const
{
return m_hasTemplateParamList ? new ParamIterator(m_templateParams) : 0;
}
IMemberReferenceIterator *MemberHandler::references() const
{
return new MemberReferenceIterator(m_references);
}
IMemberReferenceIterator *MemberHandler::referencedBy() const
{
return new MemberReferenceIterator(m_referencedBy);
}
ILinkedTextIterator *MemberHandler::initializer() const
{
return new LinkedTextIterator(m_initializer);
}
ILinkedTextIterator *MemberHandler::exceptions() const
{
return new LinkedTextIterator(m_exception);
}
IMemberReferenceIterator *MemberHandler::reimplementedBy() const
{
return new MemberReferenceIterator(m_reimplementedBy);
}
IDocRoot *MemberHandler::briefDescription() const
{
return m_brief;
}
IDocRoot *MemberHandler::detailedDescription() const
{
return m_detailed;
}
IDocRoot *MemberHandler::inbodyDescription() const
{
return m_inbody;
}

View File

@ -0,0 +1,252 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef _MEMBERHANDLER_H
#define _MEMBERHANDLER_H
#include <qstring.h>
#include <qlist.h>
#include <qxml.h>
#include <doxmlintf.h>
#include "basehandler.h"
#include "baseiterator.h"
#include "stringimpl.h"
class MainHandler;
class CompoundHandler;
class SectionHandler;
class ParamHandler;
class LinkedTextImpl;
class LinkedTextHandler;
class DocHandler;
class MemberReference : public IMemberReference
{
public:
virtual ~MemberReference() {}
virtual IMember *member() const;
virtual const IString *name() const { return &m_name; }
virtual const IString *scope() const { return &m_scope; }
virtual const IString *protection() const { return &m_protection; }
virtual const IString *virtualness() const { return &m_virtualness; }
virtual const IString *ambiguityScope() const { return &m_ambiguityScope; }
void initialize(MainHandler *m);
QString m_memId;
StringImpl m_name;
StringImpl m_scope;
StringImpl m_virtualness;
StringImpl m_protection;
StringImpl m_ambiguityScope;
MainHandler *m_mainHandler;
};
class MemberReferenceIterator : public BaseIterator<IMemberReferenceIterator,IMemberReference,MemberReference>
{
public:
MemberReferenceIterator(const QList<MemberReference> &list) :
BaseIterator<IMemberReferenceIterator,IMemberReference,MemberReference>(list) {}
};
class MemberHandler : public IDefine,
public IProperty,
public IVariable,
public ITypedef,
public IFunction,
public ISignal,
public IPrototype,
public IFriend,
public IDCOP,
public ISlot,
public IEnum,
public IEnumValue,
public BaseHandler<MemberHandler>
{
public:
virtual void startMember(const QXmlAttributes& attrib);
virtual void endMember();
virtual void startParam(const QXmlAttributes& attrib);
virtual void startType(const QXmlAttributes& attrib);
virtual void startName(const QXmlAttributes& attrib);
virtual void endName();
virtual void startRead(const QXmlAttributes& attrib);
virtual void endRead();
virtual void startWrite(const QXmlAttributes& attrib);
virtual void endWrite();
virtual void startDefinition(const QXmlAttributes& attrib);
virtual void endDefinition();
virtual void startArgsString(const QXmlAttributes& attrib);
virtual void endArgsString();
virtual void startBriefDesc(const QXmlAttributes& attrib);
virtual void startDetailedDesc(const QXmlAttributes& attrib);
virtual void startInbodyDesc(const QXmlAttributes& attrib);
virtual void startLocation(const QXmlAttributes& attrib);
virtual void startReferences(const QXmlAttributes& attrib);
virtual void endReferences();
virtual void startReferencedBy(const QXmlAttributes& attrib);
virtual void endReferencedBy();
virtual void startReimplements(const QXmlAttributes& attrib);
virtual void endReimplements();
virtual void startReimplementedBy(const QXmlAttributes& attrib);
virtual void endReimplementedBy();
virtual void startInitializer(const QXmlAttributes& attrib);
virtual void startException(const QXmlAttributes& attrib);
virtual void startEnumValue(const QXmlAttributes& attrib);
virtual void startEnumValue2(const QXmlAttributes& attrib);
virtual void startTemplateParamList(const QXmlAttributes &attrib);
virtual void endTemplateParamList();
MemberHandler(IBaseHandler *parent);
virtual ~MemberHandler();
// IMember implementation
virtual ICompound *compound() const;
virtual ISection *section() const;
virtual MemberKind kind() const
{ return m_kind; }
virtual const IString *kindString() const
{ return &m_kindString; }
virtual const IString *id() const
{ return &m_id; }
virtual const IString *protection() const
{ return &m_protection; }
virtual const IString *virtualness() const
{ return &m_virtualness; }
virtual const IString *name() const
{ return &m_name; }
virtual const IString *readAccessor() const
{ return &m_read; }
virtual const IString *writeAccessor() const
{ return &m_write; }
virtual const IString *definition() const
{ return &m_definition; }
virtual const IString *argsstring() const
{ return &m_argsstring; }
virtual bool isConst() const
{ return m_isConst; }
virtual bool isVolatile() const
{ return m_isVolatile; }
virtual bool isStatic() const
{ return m_isStatic; }
virtual bool isExplicit() const
{ return m_isExplicit; }
virtual bool isInline() const
{ return m_isInline; }
virtual bool isMutable() const
{ return m_isMutable; }
virtual bool isReadable() const
{ return m_isReadable; }
virtual bool isWritable() const
{ return m_isWritable; }
virtual ILinkedTextIterator *type() const;
virtual const IString *typeString() const;
virtual IParamIterator *parameters() const;
virtual IParamIterator *templateParameters() const;
virtual IMemberReferenceIterator *references() const;
virtual IMemberReferenceIterator *referencedBy() const;
virtual ILinkedTextIterator *initializer() const;
virtual ILinkedTextIterator *exceptions() const;
virtual const IString *bodyFile() const
{ return &m_bodyFile; }
virtual int bodyStart() const
{ return m_bodyStart; }
virtual int bodyEnd() const
{ return m_bodyEnd; }
virtual const IString *definitionFile() const
{ return &m_defFile; }
virtual int definitionLine() const
{ return m_defLine; }
virtual IMemberReference *reimplements() const
{ return m_reimplements; }
virtual IMemberReferenceIterator *reimplementedBy() const;
virtual IDocRoot *briefDescription() const;
virtual IDocRoot *detailedDescription() const;
virtual IDocRoot *inbodyDescription() const;
// IEnum
virtual IMemberIterator *enumValues() const;
void initialize(MainHandler *m);
void setCompoundHandler(CompoundHandler *c);
void setSectionHandler(SectionHandler *s);
private:
// XML elements:
// -----------------
QList<ParamHandler> m_templateParams; // templateparamlist
QList<LinkedTextImpl> m_type; // type
StringImpl m_definition; // definition
StringImpl m_argsstring; // argsstring
StringImpl m_name; // name
StringImpl m_read; // read
StringImpl m_write; // write
MemberReference *m_reimplements; // reimplements
QList<MemberReference> m_reimplementedBy; // reimplementedby
QList<ParamHandler> m_params; // param
QList<MemberHandler> m_enumValues; // enumvalue
QList<LinkedTextImpl> m_initializer; // initializer
QList<LinkedTextImpl> m_exception; // exceptions
DocHandler *m_brief; // briefdescription
DocHandler *m_detailed; // detaileddescription
DocHandler *m_inbody; // inbodydescription
// location
StringImpl m_defFile; // - file
int m_defLine; // - line
StringImpl m_bodyFile; // - bodyfile
int m_bodyStart; // - bodystart
int m_bodyEnd; // - bodyend
QList<MemberReference> m_references; // references
QList<MemberReference> m_referencedBy; // referencedby
// XML attributes:
// ---------------
MemberKind m_kind; // kind
StringImpl m_kindString; // kind as a string
StringImpl m_id; // id
StringImpl m_protection; // prot
bool m_isStatic; // static
bool m_isConst; // const
bool m_isExplicit; // explicit
bool m_isInline; // inline
StringImpl m_virtualness; // virt
bool m_isVolatile; // volatile
bool m_isMutable; // mutable
bool m_isReadable; // readable
bool m_isWritable; // writable
CompoundHandler *m_compound;
SectionHandler *m_section;
StringImpl m_typeString;
LinkedTextHandler *m_linkedTextHandler;
bool m_insideTemplateParamList;
bool m_hasTemplateParamList;
IBaseHandler *m_parent;
};
class MemberIterator : public BaseIteratorVia<IMemberIterator,
IMember,
MemberHandler,
IFunction>
{
public:
MemberIterator(const QList<MemberHandler> &list) :
BaseIteratorVia<IMemberIterator,IMember,MemberHandler,IFunction>(list) {}
};
void memberhandler_init();
void memberhandler_exit();
#endif

View File

@ -0,0 +1,158 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include "paramhandler.h"
#include "memberhandler.h"
#include "linkedtexthandler.h"
#include "debug.h"
#include "dochandler.h"
TemplateParamListHandler::TemplateParamListHandler(IBaseHandler *parent) : m_parent(parent)
{
addStartHandler("param",this,&TemplateParamListHandler::startParam);
addEndHandler("templateparamlist",this,&TemplateParamListHandler::endTemplateParamList);
}
void TemplateParamListHandler::startParam(const QXmlAttributes& attrib)
{
ParamHandler *ph = new ParamHandler(this);
ph->startParam(attrib);
m_templateParams.append(ph);
}
void TemplateParamListHandler::endParam()
{
}
void TemplateParamListHandler::startTemplateParamList(const QXmlAttributes& /*attrib*/)
{
m_parent->setDelegate(this);
debug(2,"templateparamlist\n");
}
void TemplateParamListHandler::endTemplateParamList()
{
m_parent->setDelegate(0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
ParamHandler::ParamHandler(IBaseHandler *parent) : m_brief(0), m_parent(parent)
{
addEndHandler("param",this,&ParamHandler::endParam);
addStartHandler("type",this,&ParamHandler::startType);
addStartHandler("declname");
addEndHandler("declname",this,&ParamHandler::endDeclName);
addStartHandler("defname");
addEndHandler("defname",this,&ParamHandler::endDefName);
addStartHandler("array");
addEndHandler("array",this,&ParamHandler::endArray);
addStartHandler("attribute");
addEndHandler("attribute",this,&ParamHandler::endAttrib);
addStartHandler("briefdescription",this,&ParamHandler::startBriefDesc);
addStartHandler("defval",this,&ParamHandler::startDefVal);
m_linkedTextHandler = 0;
}
ParamHandler::~ParamHandler()
{
delete m_brief;
delete m_linkedTextHandler;
}
void ParamHandler::startParam(const QXmlAttributes& /*attrib*/)
{
m_parent->setDelegate(this);
debug(2,"param\n");
}
void ParamHandler::endParam()
{
m_parent->setDelegate(0);
}
void ParamHandler::startType(const QXmlAttributes& /*attrib*/)
{
delete m_linkedTextHandler;
m_linkedTextHandler = new LinkedTextHandler(this,m_type);
m_linkedTextHandler->start("type");
debug(2,"param type\n");
}
void ParamHandler::endDeclName()
{
m_declName = m_curString.stripWhiteSpace();
debug(2,"member declName='%s'\n",m_declName.data());
}
void ParamHandler::endDefName()
{
m_defName = m_curString.stripWhiteSpace();
debug(2,"member defName='%s'\n",m_defName.data());
}
void ParamHandler::endAttrib()
{
m_attrib = m_curString.stripWhiteSpace();
debug(2,"member attrib='%s'\n",m_attrib.data());
}
void ParamHandler::endArray()
{
m_array = m_curString.stripWhiteSpace();
debug(2,"member array='%s'\n",m_array.data());
}
void ParamHandler::startDefVal(const QXmlAttributes& /*attrib*/)
{
delete m_linkedTextHandler;
m_linkedTextHandler = new LinkedTextHandler(this,m_defVal);
m_linkedTextHandler->start("defval");
debug(2,"member defVal\n");
}
void ParamHandler::startBriefDesc(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_brief = docHandler;
}
ILinkedTextIterator *ParamHandler::type() const
{
return new LinkedTextIterator(m_type);
}
ILinkedTextIterator *ParamHandler::defaultValue() const
{
return new LinkedTextIterator(m_defVal);
}
IDocRoot *ParamHandler::briefDescription() const
{
return m_brief;
}

View File

@ -0,0 +1,103 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef _PARAMHANDLER_H
#define _PARAMHANDLER_H
#include <qstring.h>
#include <qlist.h>
#include <qxml.h>
#include <doxmlintf.h>
#include "stringimpl.h"
#include "basehandler.h"
#include "baseiterator.h"
class LinkedTextImpl;
class LinkedTextHandler;
class DocHandler;
class ParamHandler : public IParam, public BaseHandler<ParamHandler>
{
public:
virtual void startParam(const QXmlAttributes& attrib);
virtual void endParam();
virtual void startType(const QXmlAttributes& attrib);
virtual void endDeclName();
virtual void endDefName();
virtual void endAttrib();
virtual void endArray();
virtual void startDefVal(const QXmlAttributes& attrib);
virtual void startBriefDesc(const QXmlAttributes& attrib);
ParamHandler(IBaseHandler *parent);
virtual ~ParamHandler();
// IParam
virtual ILinkedTextIterator *type() const;
virtual const IString * declarationName() const { return &m_declName; }
virtual const IString * definitionName() const { return &m_defName; }
virtual const IString * attrib() const { return &m_attrib; }
virtual const IString * arraySpecifier() const { return &m_array; }
virtual ILinkedTextIterator *defaultValue() const;
virtual IDocRoot *briefDescription() const;
private:
// XML elements:
// -------------
QList<LinkedTextImpl> m_type; // type
StringImpl m_declName; // declname
StringImpl m_defName; // defname
StringImpl m_array; // array
QList<LinkedTextImpl> m_defVal; // defval
DocHandler *m_brief; // briefdescription
StringImpl m_attrib; // TODO: not yet in XML output
IBaseHandler *m_parent;
LinkedTextHandler *m_linkedTextHandler;
};
class ParamIterator : public BaseIterator<IParamIterator,IParam,ParamHandler>
{
public:
ParamIterator(const QList<ParamHandler> &list) :
BaseIterator<IParamIterator,IParam,ParamHandler>(list) {}
};
class TemplateParamListHandler : public BaseHandler<TemplateParamListHandler>
{
public:
virtual void startParam(const QXmlAttributes& attrib);
virtual void endParam();
virtual void startTemplateParamList(const QXmlAttributes& attrib);
virtual void endTemplateParamList();
TemplateParamListHandler(IBaseHandler *parent);
virtual ~TemplateParamListHandler() {}
ParamIterator* templateParams() { return new ParamIterator(m_templateParams); }
protected:
IBaseHandler *m_parent;
QList<ParamHandler> m_templateParams;
};
#endif

View File

@ -0,0 +1,170 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include "mainhandler.h"
#include "compoundhandler.h"
#include "sectionhandler.h"
#include "memberhandler.h"
#include "linkedtexthandler.h"
#include "paramhandler.h"
#include "dochandler.h"
#include "debug.h"
class SectionTypeMap
{
public:
SectionTypeMap() : m_map(37)
{
m_map.setAutoDelete(TRUE);
m_map.insert("user-defined",new int(ISection::UserDefined));
m_map.insert("public-type",new int(ISection::PubTypes));
m_map.insert("public-func",new int(ISection::PubFuncs));
m_map.insert("public-attrib",new int(ISection::PubAttribs));
m_map.insert("public-slot",new int(ISection::PubSlots));
m_map.insert("signal",new int(ISection::Signals));
m_map.insert("dcop-func",new int(ISection::DCOPFuncs));
m_map.insert("property",new int(ISection::Properties));
m_map.insert("event",new int(ISection::Events));
m_map.insert("public-static-func",new int(ISection::PubStatFuncs));
m_map.insert("public-static-attrib",new int(ISection::PubStatAttribs));
m_map.insert("protected-type",new int(ISection::ProTypes));
m_map.insert("protected-func",new int(ISection::ProFuncs));
m_map.insert("protected-attrib",new int(ISection::ProAttribs));
m_map.insert("protected-slot",new int(ISection::ProSlots));
m_map.insert("protected-static-func",new int(ISection::ProStatFuncs));
m_map.insert("protected-static-attrib",new int(ISection::ProStatAttribs));
m_map.insert("package-type",new int(ISection::PacTypes));
m_map.insert("package-func",new int(ISection::PacFuncs));
m_map.insert("package-attrib",new int(ISection::PacAttribs));
m_map.insert("package-static-func",new int(ISection::PacStatFuncs));
m_map.insert("package-static-attrib",new int(ISection::PacStatAttribs));
m_map.insert("private-type",new int(ISection::PriTypes));
m_map.insert("private-func",new int(ISection::PriFuncs));
m_map.insert("private-attrib",new int(ISection::PriAttribs));
m_map.insert("private-slot",new int(ISection::PriSlots));
m_map.insert("private-static-func",new int(ISection::PriStatFuncs));
m_map.insert("private-static-attrib",new int(ISection::PriStatAttribs));
m_map.insert("friend",new int(ISection::Friend));
m_map.insert("related",new int(ISection::Related));
m_map.insert("define",new int(ISection::Defines));
m_map.insert("prototype",new int(ISection::Prototypes));
m_map.insert("typedef",new int(ISection::Typedefs));
m_map.insert("enum",new int(ISection::Enums));
m_map.insert("func",new int(ISection::Functions));
m_map.insert("var",new int(ISection::Variables));
}
ISection::SectionKind map(const QString &s)
{
int *val = m_map.find(s.utf8());
if (val==0)
{
debug(1,"Warning: '%s' is an invalid section type\n",s.data());
return ISection::Invalid;
}
else return (ISection::SectionKind)*val;
}
private:
QDict<int> m_map;
};
static SectionTypeMap *s_typeMap;
void sectionhandler_init()
{
s_typeMap = new SectionTypeMap;
}
void sectionhandler_exit()
{
delete s_typeMap;
}
SectionHandler::SectionHandler(IBaseHandler *parent) : m_parent(parent)
{
//printf("SectionHandler::SectionHandler()\n");
m_members.setAutoDelete(TRUE);
addEndHandler("sectiondef",this,&SectionHandler::endSection);
addStartHandler("memberdef",this,&SectionHandler::startMember);
addStartHandler("header",this,&SectionHandler::startHeader);
addEndHandler("header",this,&SectionHandler::endHeader);
addStartHandler("description",this,&SectionHandler::startDescription);
}
SectionHandler::~SectionHandler()
{
debug(2,"SectionHandler::~SectionHandler()\n");
}
void SectionHandler::startSection(const QXmlAttributes& attrib)
{
m_parent->setDelegate(this);
m_kindString = attrib.value("kind");
m_kind = s_typeMap->map(m_kindString);
debug(2,"section kind='%s'\n",m_kindString.data());
}
void SectionHandler::startDescription(const QXmlAttributes& attrib)
{
DocHandler *docHandler = new DocHandler(this);
docHandler->startDoc(attrib);
m_description = docHandler;
}
void SectionHandler::endSection()
{
m_parent->setDelegate(0);
}
void SectionHandler::startMember(const QXmlAttributes& attrib)
{
MemberHandler *memHandler = new MemberHandler(this);
memHandler->startMember(attrib);
m_members.append(memHandler);
}
void SectionHandler::startHeader(const QXmlAttributes&)
{
m_header="";
m_curString="";
}
void SectionHandler::endHeader()
{
m_header = m_curString.stripWhiteSpace();
debug(2,"member header='%s'\n",m_header.data());
}
void SectionHandler::initialize(CompoundHandler *ch)
{
QListIterator<MemberHandler> mli(m_members);
MemberHandler *mh;
for (;(mh=mli.current());++mli)
{
mh->setCompoundHandler(ch);
ch->insertMember(mh);
mh->setSectionHandler(this);
}
}
IDocRoot *SectionHandler::description() const
{
return m_description;
}
IMemberIterator *SectionHandler::members() const
{
return new MemberIterator(m_members);
}

View File

@ -0,0 +1,102 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef _SECTIONHANDLER_H
#define _SECTIONHANDLER_H
#include <qstring.h>
#include <qlist.h>
#include <qxml.h>
#include <doxmlintf.h>
#include "basehandler.h"
class SectionIterator :
public BaseIterator<ISectionIterator,ISection,SectionHandler>
{
public:
SectionIterator(const QList<SectionHandler> &list) :
BaseIterator<ISectionIterator,ISection,SectionHandler>(list) {}
};
class SectionHandler : public IUserDefined, public BaseHandler<SectionHandler>
{
public:
virtual void startMember(const QXmlAttributes& attrib);
virtual void startHeader(const QXmlAttributes& attrib);
virtual void startSection(const QXmlAttributes& attrib);
virtual void startDescription(const QXmlAttributes& attrib);
virtual void endSection();
virtual void endHeader();
SectionHandler(IBaseHandler *parent);
virtual ~SectionHandler();
// ISection
virtual const IString *kindString() const
{ return &m_kindString; }
virtual SectionKind kind() const
{ return m_kind; }
IDocRoot *description() const;
virtual IMemberIterator *members() const;
virtual bool isStatic() const
{
return m_kind==PubStatFuncs || m_kind==PubStatAttribs ||
m_kind==ProStatFuncs || m_kind==ProStatAttribs ||
m_kind==PriStatFuncs || m_kind==PriStatAttribs;
}
virtual bool isPublic() const
{
return !isProtected() && !isPrivate();
}
virtual bool isProtected() const
{
return m_kind==ProTypes || m_kind==ProFuncs || m_kind==ProAttribs ||
m_kind==ProSlots || m_kind==ProStatFuncs || m_kind==ProStatAttribs;
}
virtual bool isPrivate() const
{
return m_kind==PriTypes || m_kind==PriFuncs || m_kind==PriAttribs ||
m_kind==PriSlots || m_kind==PriStatFuncs || m_kind==PriStatAttribs;
}
void initialize(CompoundHandler *c);
// IUserDefined implementation
virtual const IString *header() const
{
return &m_header;
}
private:
IBaseHandler *m_parent;
// XML elements:
// -------------
StringImpl m_header; // header
DocHandler* m_description; // description
QList<MemberHandler> m_members; // memberdef
// XML attributes:
// ---------------
SectionKind m_kind; // kind
StringImpl m_kindString; // kind as a string
};
void sectionhandler_init();
void sectionhandler_exit();
#endif

View File

@ -0,0 +1,38 @@
#ifndef STRINGIMPL_H
#define STRINGIMPL_H
#include <qstring.h>
#include "doxmlintf.h"
class StringImpl : public IString
{
public:
StringImpl() {}
StringImpl(const QString &str) : m_str(str) {}
StringImpl &operator=(const QString &str)
{ m_str=str; return *this; }
virtual ~StringImpl() {}
const char *data() const
{ return m_str.data(); }
// IString
const char *latin1() const
{ return m_str.latin1(); }
const char *utf8() const
{ m_cstr = m_str.utf8(); return m_cstr.data(); }
unsigned short unicodeCharAt(int index) const
{ return m_str.unicode()[index].unicode(); }
bool isEmpty() const
{ return m_str.isEmpty(); }
int length() const
{ return m_str.length(); }
operator QString() const { return m_str; }
private:
QString m_str;
mutable QCString m_cstr; // used as a cache for m_str.utf8() to avoid returning a temporary
};
#endif

View File

@ -0,0 +1,18 @@
include_directories(
../include
${PROJECT_SOURCE_DIR}/libversion
${PROJECT_SOURCE_DIR}/qtools
)
add_executable(doxmlparser_test
main.cpp
)
target_link_libraries(doxmlparser_test
doxmlparser
doxygen_version
qtools
${COVERAGE_LINKER_FLAGS}
)

View File

@ -0,0 +1,776 @@
/******************************************************************************
*
* $Id$
*
*
* Copyright (C) 1997-2006 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <doxmlintf.h>
#include <qstring.h>
#include "version.h"
/*! Dumps the contents of a hyperlinked text fragment as plain text to the
* output.
*/
QString linkedTextToString(ILinkedTextIterator *ti)
{
QString result;
ILinkedText *lt=0;
for (ti->toFirst();(lt=ti->current());ti->toNext())
{
switch (lt->kind())
{
case ILinkedText::Kind_Text: // plain text
result+=dynamic_cast<ILT_Text*>(lt)->text()->latin1(); break;
case ILinkedText::Kind_Ref: // a link
result+=dynamic_cast<ILT_Ref *>(lt)->text()->latin1(); break;
}
}
return result;
}
/*! Macro for printing an indented message. */
#define InPrint(x) printf("%s",indent.latin1()), printf x;
/*! Dumps the contents of a documentation block to stdout.
* @note This function will call itself recursively.
* @param doc The root of the documentation tree.
* @param level The indent level.
*/
void DumpDoc(IDoc *doc,int level)
{
if (doc==0) return;
QString indent;
indent.fill(' ',level);
//printf(" doc node kind='%d'\n",doc->kind());
switch (doc->kind())
{
case IDoc::Para:
{
InPrint(("<para>\n"));
IDocPara *par = dynamic_cast<IDocPara*>(doc);
ASSERT(par!=0);
IDocIterator *di = par->contents();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("</para>\n"));
}
break;
case IDoc::Text:
{
IDocText *txt = dynamic_cast<IDocText*>(doc);
ASSERT(txt!=0);
InPrint(("<text value='%s' markup=%d headingLevel=%d/>\n",
txt->text()->latin1(),txt->markup(),txt->headingLevel()));
}
break;
case IDoc::MarkupModifier:
{
IDocMarkupModifier *md = dynamic_cast<IDocMarkupModifier*>(doc);
ASSERT(md!=0);
InPrint(("<markup modifier enabled=%d markup=%d headingLevel=%d/>\n",
md->enabled(),md->markup(),md->headingLevel()));
}
break;
case IDoc::ItemizedList:
{
InPrint(("<itemized list>\n"));
IDocItemizedList *list = dynamic_cast<IDocItemizedList*>(doc);
ASSERT(list!=0);
IDocIterator *di = list->elements();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("</itemized list>\n"));
}
break;
case IDoc::OrderedList:
{
InPrint(("<ordered list>\n"));
IDocOrderedList *list = dynamic_cast<IDocOrderedList*>(doc);
ASSERT(list!=0);
IDocIterator *di = list->elements();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("</ordered list>\n"));
}
break;
case IDoc::ListItem:
{
InPrint(("<list item>\n"));
IDocListItem *li = dynamic_cast<IDocListItem*>(doc);
ASSERT(li!=0);
IDocIterator *di = li->contents();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("</list item>\n"));
}
break;
case IDoc::ParameterItem:
{
IDocParameterItem *item = dynamic_cast<IDocParameterItem*>(doc);
InPrint(("<parameter item>\n"));
IDocIterator *di = item->paramNames();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
DumpDoc(item->description(),level+1);
InPrint(("</parameter item>\n"));
}
break;
case IDoc::ParameterList:
{
IDocParameterList *list = dynamic_cast<IDocParameterList*>(doc);
InPrint(("<parameter list type=%d>\n",list->sectType()));
IDocIterator *di = list->params();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("</parameter list>\n"));
ASSERT(list!=0);
}
break;
case IDoc::Parameter:
{
IDocParameter *par = dynamic_cast<IDocParameter*>(doc);
ASSERT(par!=0);
InPrint(("<parameter name=%s/>\n",par->name()->latin1()));
}
break;
case IDoc::SimpleSect:
{
IDocSimpleSect *ss = dynamic_cast<IDocSimpleSect*>(doc);
ASSERT(ss!=0);
InPrint(("<simplesect type=%s>\n",ss->typeString()->latin1()));
DumpDoc(ss->title(),level+1);
DumpDoc(ss->description(),level+1);
InPrint(("<simplesect/>\n"));
}
break;
case IDoc::Title:
{
InPrint(("<title>\n"));
IDocTitle *t = dynamic_cast<IDocTitle*>(doc);
ASSERT(t!=0);
IDocIterator *di = t->title();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
InPrint(("<title/>\n"));
}
break;
case IDoc::Ref:
{
IDocRef *ref = dynamic_cast<IDocRef*>(doc);
ASSERT(ref!=0);
InPrint(("<ref id=%s text=%s/>\n",
ref->refId()->latin1(),ref->text()->latin1()));
}
break;
case IDoc::VariableList:
{
InPrint(("<variablelist>\n"));
IDocVariableList *vl = dynamic_cast<IDocVariableList*>(doc);
ASSERT(vl!=0);
IDocIterator *di = vl->entries();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("<variablelist/>\n"));
}
break;
case IDoc::VariableListEntry:
{
IDocVariableListEntry *vle = dynamic_cast<IDocVariableListEntry*>(doc);
ASSERT(vle!=0);
ILinkedTextIterator *lti = vle->term();
QString term = linkedTextToString(lti);
lti->release();
InPrint(("<variablelistentry term=%s>\n",term.latin1()));
DumpDoc(vle->description(),level+1);
InPrint(("<variablelistentry/>\n"));
}
break;
case IDoc::HRuler:
{
IDocHRuler *hr = dynamic_cast<IDocHRuler*>(doc);
ASSERT(hr!=0);
InPrint(("<hruler/>\n"));
}
break;
case IDoc::LineBreak:
{
IDocLineBreak *lb = dynamic_cast<IDocLineBreak*>(doc);
ASSERT(lb!=0);
InPrint(("<linebreak/>\n"));
}
break;
case IDoc::ULink:
{
IDocULink *ul = dynamic_cast<IDocULink*>(doc);
ASSERT(ul!=0);
InPrint(("<ulink url='%s' text='%s'/>\n",ul->url()->latin1(),ul->text()->latin1()));
}
break;
case IDoc::EMail:
{
IDocEMail *em = dynamic_cast<IDocEMail*>(doc);
ASSERT(em!=0);
InPrint(("<email address='%s'/>\n",em->address()->latin1()));
}
break;
case IDoc::Link:
{
IDocLink *lk = dynamic_cast<IDocLink*>(doc);
ASSERT(lk!=0);
InPrint(("<link refid='%s' text='%s'/>\n",lk->refId()->latin1(),lk->text()->latin1()));
}
break;
case IDoc::ProgramListing:
{
IDocProgramListing *pl = dynamic_cast<IDocProgramListing*>(doc);
ASSERT(pl!=0);
InPrint(("<programlisting>\n"));
IDocIterator *cli = pl->codeLines();
IDoc *cl;
for (cli->toFirst();(cl=cli->current());cli->toNext())
{
DumpDoc(cl,level+1);
}
cli->release();
InPrint(("</programlisting>\n"));
}
break;
case IDoc::CodeLine:
{
IDocCodeLine *cl = dynamic_cast<IDocCodeLine*>(doc);
ASSERT(cl!=0);
InPrint(("<codeline lineNumber=%d refId='%s'>\n",cl->lineNumber(),cl->refId()->latin1()));
IDocIterator *cei = cl->codeElements();
IDoc *ce;
for (cei->toFirst();(ce=cei->current());cei->toNext())
{
DumpDoc(ce,level+1);
}
cei->release();
InPrint(("</codeline>\n"));
}
break;
case IDoc::Highlight:
{
IDocHighlight *hl = dynamic_cast<IDocHighlight*>(doc);
ASSERT(hl!=0);
InPrint(("<highlight kind=%d>\n",hl->kind()));
IDocIterator *cei = hl->codeElements();
IDoc *ce;
for (cei->toFirst();(ce=cei->current());cei->toNext())
{
DumpDoc(ce,level+1);
}
cei->release();
InPrint(("</highlight>\n"));
}
break;
case IDoc::Formula:
{
IDocFormula *fm = dynamic_cast<IDocFormula*>(doc);
ASSERT(fm!=0);
InPrint(("<formula id='%s' text='%s'/>\n",fm->id()->latin1(),fm->text()->latin1()));
}
break;
case IDoc::Image:
{
IDocImage *img = dynamic_cast<IDocImage*>(doc);
ASSERT(img!=0);
InPrint(("<image name='%s' caption='%s'/>\n",img->name()->latin1(),img->caption()->latin1()));
}
break;
case IDoc::DotFile:
{
IDocDotFile *df = dynamic_cast<IDocDotFile*>(doc);
ASSERT(df!=0);
InPrint(("<dotfile name='%s' caption='%s'/>\n",df->name()->latin1(),df->caption()->latin1()));
}
break;
case IDoc::IndexEntry:
{
IDocIndexEntry *ie = dynamic_cast<IDocIndexEntry*>(doc);
ASSERT(ie!=0);
InPrint(("<indexentry primary='%s' secondary='%s'/>\n",ie->primary()->latin1(),ie->secondary()->latin1()));
}
break;
case IDoc::Table:
{
IDocTable *tbl = dynamic_cast<IDocTable*>(doc);
ASSERT(tbl!=0);
InPrint(("<table numcols=%d caption='%s'>\n",tbl->numColumns(),tbl->caption()->latin1()));
IDocIterator *ri = tbl->rows();
IDoc *row;
for (ri->toFirst();(row=ri->current());ri->toNext())
{
DumpDoc(row,level+1);
}
ri->release();
InPrint(("</table>\n"));
}
break;
case IDoc::Row:
{
IDocRow *row = dynamic_cast<IDocRow*>(doc);
ASSERT(row!=0);
InPrint(("<row>\n"));
IDocIterator *ei = row->entries();
IDoc *e;
for (ei->toFirst();(e=ei->current());ei->toNext())
{
DumpDoc(e,level+1);
}
ei->release();
InPrint(("</row>\n"));
}
break;
case IDoc::Entry:
{
IDocEntry *ent = dynamic_cast<IDocEntry*>(doc);
ASSERT(ent!=0);
InPrint(("<entry>\n"));
IDocIterator *di = ent->contents();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("</entry>\n"));
}
break;
case IDoc::Section:
{
IDocSection *sec = dynamic_cast<IDocSection*>(doc);
ASSERT(sec!=0);
InPrint(("<section id='%s' level=%d>\n",
sec->id()->latin1(),sec->level()));
DumpDoc(sec->title(),level+1);
IDocIterator *di = sec->paragraphs();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di=sec->subSections();
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
IDocInternal *intern = sec->internal();
if (intern)
{
DumpDoc(intern,level+1);
}
InPrint(("</section>\n"));
}
break;
case IDoc::Internal:
{
IDocInternal *intern = dynamic_cast<IDocInternal*>(doc);
ASSERT(intern!=0);
InPrint(("<internal>\n"));
IDocIterator *di = intern->paragraphs();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di=intern->subSections();
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
InPrint(("</internal>\n"));
}
break;
case IDoc::Copy:
{
IDocCopy *cpy = dynamic_cast<IDocCopy*>(doc);
ASSERT(cpy!=0);
InPrint(("<copydoc>\n"));
IDocIterator *di = cpy->contents();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("<copydoc/>\n"));
}
break;
case IDoc::TocItem:
{
IDocTocItem *ti = dynamic_cast<IDocTocItem*>(doc);
ASSERT(ti!=0);
InPrint(("<tocitem id=\"%s\" title=\"%s\"/>\n",
ti->id()->latin1(),ti->title()->latin1()));
}
break;
case IDoc::TocList:
{
IDocTocList *tl = dynamic_cast<IDocTocList*>(doc);
ASSERT(tl!=0);
InPrint(("<toclist>\n"));
IDocIterator *di = tl->elements();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("<toclist/>\n"));
}
break;
case IDoc::Verbatim:
{
IDocVerbatim *vt = dynamic_cast<IDocVerbatim*>(doc);
ASSERT(vt!=0);
const char *s=0;
switch (vt->type())
{
case IDocVerbatim::Verbatim: s="verbatim"; break;
case IDocVerbatim::HtmlOnly: s="htmlonly"; break;
case IDocVerbatim::LatexOnly: s="latexonly"; break;
default:
printf("Invalid verbatim type!\n");
}
InPrint(("<verbatim %s>\n",s));
InPrint(("%s",vt->text()->latin1()));
InPrint(("</verbatim>\n"));
}
break;
case IDoc::Anchor:
{
IDocAnchor *anc = dynamic_cast<IDocAnchor*>(doc);
ASSERT(anc!=0);
InPrint(("<anchor id='%s'/>\n",anc->id()->latin1()));
}
break;
case IDoc::Symbol:
{
IDocSymbol *sym = dynamic_cast<IDocSymbol*>(doc);
ASSERT(sym!=0);
InPrint(("<symbol type=%s letter=%c/>\n",
sym->typeString()->latin1(),sym->letter()));
}
break;
case IDoc::Root:
{
InPrint(("<root>\n"));
IDocRoot *root = dynamic_cast<IDocRoot*>(doc);
ASSERT(root!=0);
IDocIterator *di = root->contents();
IDoc *pdoc;
for (di->toFirst();(pdoc=di->current());di->toNext())
{
DumpDoc(pdoc,level+1);
}
di->release();
InPrint(("</root>\n"));
}
break;
default:
printf("Found unsupported node type %d!\n",doc->kind());
break;
}
}
void DumpGraph(IGraph *graph)
{
if (graph==0) { printf(" --- no graph ---\n"); return; }
printf(" --- graph ----\n");
INodeIterator *ni = graph->nodes();
INode *node;
for (ni->toFirst();(node=ni->current());ni->toNext())
{
printf(" --- node id=%s label=%s linkId=%s\n",
node->id()->latin1(),
node->label()->latin1(),
node->linkId()->latin1()
);
IChildNodeIterator *cni = node->children();
IChildNode *cn;
for (cni->toFirst();(cn=cni->current());cni->toNext())
{
printf(" + child id=%s label=%s relation=%s\n",
cn->node()->id()->latin1(),
cn->node()->label()->latin1(),
cn->relationString()->latin1()
);
IEdgeLabelIterator *eli = cn->edgeLabels();
IEdgeLabel *el;
for (eli->toFirst();(el=eli->current());eli->toNext())
{
printf(" edgeLabel=%s\n",el->label()->latin1());
}
eli->release();
}
cni->release();
}
ni->release();
printf(" --- end graph ----\n");
}
void DumpParamList(IParamIterator *pli,int indent)
{
QString indentStr;
indentStr.fill(' ',indent);
IParam *par;
for (pli->toFirst();(par=pli->current());pli->toNext())
{
ILinkedTextIterator *lti = par->type();
QString parType = linkedTextToString(lti);
lti->release();
lti = par->defaultValue();
QString defVal = linkedTextToString(lti);
lti->release();
printf("%sParam type=%s decl_name=%s def_name=%s defvalue=%s\n",
indentStr.data(), parType.latin1(),
par->declarationName()->latin1(),
par->definitionName()->latin1(),
defVal.latin1());
}
}
int main(int argc,char **argv)
{
int locArgc = argc;
if (locArgc == 2)
{
if (!strcmp(argv[1],"--help"))
{
printf("Usage: %s xml_dir\n",argv[0]);
exit(0);
}
else if (!strcmp(argv[1],"--version"))
{
printf("%s version: %s\n",argv[0],getFullVersion());
exit(0);
}
}
if (locArgc!=2)
{
printf("Usage: %s xml_dir\n",argv[0]);
exit(1);
}
IDoxygen *dox = createObjectModel();
dox->setDebugLevel(4);
if (!dox->readXMLDir(argv[1]))
{
printf("Error reading %s/index.xml\n",argv[1]);
exit(1);
}
ICompoundIterator *cli = dox->compounds();
ICompound *comp;
printf("--- compound list ---------\n");
for (cli->toFirst();(comp=cli->current());cli->toNext())
{
printf("Compound name=%s id=%s kind=%s\n",
comp->name()->latin1(),comp->id()->latin1(),comp->kindString()->latin1());
ISectionIterator *sli = comp->sections();
ISection *sec;
for (sli->toFirst();(sec=sli->current());sli->toNext())
{
printf(" Section kind=%s\n",sec->kindString()->latin1());
IMemberIterator *mli = sec->members();
IMember *mem;
if( sec->kind() == ISection::UserDefined )
{
IUserDefined *group = dynamic_cast<IUserDefined*>(sec);
printf(" Title=%s\n", group->header()->latin1() );
}
for (mli->toFirst();(mem=mli->current());mli->toNext())
{
ILinkedTextIterator *lti = mem->type();
printf(" Member type=%s name=%s\n",
linkedTextToString(lti).latin1(),mem->name()->latin1());
lti->release();
IParamIterator *pli = mem->parameters();
DumpParamList(pli,6);
pli->release();
IMemberReferenceIterator *mri = mem->references();
IMemberReference *mr;
for (mri->toFirst();(mr=mri->current());mri->toNext())
{
IMember *memr = mr->member();
printf(" References %s at line %d\n",
mr->name()->latin1(),memr->bodyStart());
}
mri->release();
mri = mem->referencedBy();
for (mri->toFirst();(mr=mri->current());mri->toNext())
{
IMember *memr = mr->member();
printf(" ReferencedBy %s at line %d\n",
mr->name()->latin1(),memr->bodyStart());
}
mri->release();
if (mem->kind()==IMember::Enum) // we have found an enum
{
IEnum *e = dynamic_cast<IEnum*>(mem);
IMemberIterator *evi = e->enumValues(); // get the enum values
IMember *mev;
for (evi->toFirst();(mev=evi->current());evi->toNext())
{
IEnumValue *ev = dynamic_cast<IEnumValue*>(mev);
ILinkedTextIterator *lti = ev->initializer();
QString init = linkedTextToString(lti);
lti->release();
printf(" Enum value '%s' init='%s'\n",
ev->name()->latin1(),init.latin1());
}
evi->release();
}
pli = mem->templateParameters();
if (pli)
{
printf(" Template parameters\n");
DumpParamList(pli,8);
pli->release();
}
IDoc *doc = mem->briefDescription();
if (doc)
{
printf("===== brief description ==== \n");
DumpDoc(doc,0);
}
doc = mem->detailedDescription();
if (doc)
{
printf("===== detailed description ==== \n");
DumpDoc(doc,0);
}
}
mli->release();
}
sli->release();
IDoc *doc = comp->briefDescription();
if (doc)
{
printf("===== brief description ==== \n");
DumpDoc(doc,0);
}
doc = comp->detailedDescription();
if (doc)
{
printf("===== detailed description ==== \n");
DumpDoc(doc,0);
}
if (comp->kind()==ICompound::Class)
{
IClass *cls = dynamic_cast<IClass*>(comp);
ASSERT(cls!=0);
printf("==== inheritance graph ==== \n");
DumpGraph(cls->inheritanceGraph());
printf("==== collaboration graph ==== \n");
DumpGraph(cls->collaborationGraph());
printf("==== base classes ==== \n");
IRelatedCompoundIterator *bcli = cls->baseCompounds();
IRelatedCompound *bClass;
for (bcli->toFirst();(bClass=bcli->current());bcli->toNext())
{
ICompound *bc = bClass->compound();
printf(" + class %s\n",bc->name()->latin1());
bc->release();
}
bcli->release();
printf("==== derived classes ==== \n");
IRelatedCompoundIterator *dcli = cls->derivedCompounds();
IRelatedCompound *dClass;
for (dcli->toFirst();(dClass=dcli->current());dcli->toNext())
{
ICompound *dc = dClass->compound();
printf(" + class %s\n",dc->name()->latin1());
dc->release();
}
dcli->release();
}
else if (comp->kind()==ICompound::File)
{
IFile *file = dynamic_cast<IFile*>(comp);
ASSERT(file!=0);
printf("==== include dependency graph ==== \n");
DumpGraph(file->includeDependencyGraph());
printf("==== included by dependency graph ==== \n");
DumpGraph(file->includedByDependencyGraph());
printf("==== source ====\n");
DumpDoc(file->source(),0);
}
comp->release();
}
cli->release();
printf("---------------------------\n");
dox->release();
return 0;
}

View File

@ -0,0 +1,54 @@
find_package(Iconv)
include_directories(
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/libversion
${GENERATED_SRC}
${PROJECT_SOURCE_DIR}/qtools
${ICONV_INCLUDE_DIR}
${CLANG_INCLUDEDIR}
)
add_executable(doxyapp
doxyapp.cpp
)
add_sanitizers(doxyapp)
if (use_libclang)
find_package(LLVM REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_features(doxyapp PRIVATE cxx_alignof)
if (use_libc++)
target_compile_options(doxyapp PRIVATE -stdlib=libc++)
endif()
endif()
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
if (static_libclang)
set(CLANG_LIBS libclang clangTooling)
else() # dynamically linked version of clang
llvm_config(doxymain USE_SHARED support)
set(CLANG_LIBS libclang clang-cpp)
endif()
target_compile_definitions(doxyapp PRIVATE ${LLVM_DEFINITIONS})
endif()
target_link_libraries(doxyapp
doxymain
qtools
md5
lodepng
mscgen
doxygen_version
doxycfg
vhdlparser
${ICONV_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${SQLITE3_LIBRARIES}
${EXTRA_LIBS}
${CLANG_LIBS}
${COVERAGE_LINKER_FLAGS}
)
install(TARGETS doxyapp DESTINATION bin)

8
addon/doxyapp/README Normal file
View File

@ -0,0 +1,8 @@
This directory contains an example of how to use doxygen as
an "source parsing engine" in an application. It shows how to configure doxygen
from the application and shows how to run doxygen without generating output,
and then uses the information about the symbols found in the source code.
Note that if you use this approach your application should be licensed under the GPL.

316
addon/doxyapp/doxyapp.cpp Normal file
View File

@ -0,0 +1,316 @@
/******************************************************************************
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
/** @file
* @brief Example of how to use doxygen as part of another GPL applications
*
* This example shows how to configure and run doxygen programmatically from
* within an application without generating the usual output.
* The example should work on any Unix like OS (including Linux and Mac OS X).
*
* This example shows how to use to code parser to get cross-references information
* and it also shows how to look up symbols in a program parsed by doxygen and
* show some information about them.
*/
#include <stdlib.h>
#include <qfile.h>
#include <qdir.h>
#include "doxygen.h"
#include "outputgen.h"
#include "parserintf.h"
#include "classdef.h"
#include "namespacedef.h"
#include "filedef.h"
#include "util.h"
#include "classlist.h"
#include "config.h"
#include "filename.h"
#include "version.h"
class XRefDummyCodeGenerator : public CodeOutputInterface
{
public:
XRefDummyCodeGenerator(FileDef *fd) : m_fd(fd) {}
~XRefDummyCodeGenerator() {}
// these are just null functions, they can be used to produce a syntax highlighted
// and cross-linked version of the source code, but who needs that anyway ;-)
void codify(const char *) {}
void writeCodeLink(const char *,const char *,const char *,const char *,const char *) {}
void writeLineNumber(const char *,const char *,const char *,int) {}
virtual void writeTooltip(const char *,const DocLinkInfo &,
const char *,const char *,const SourceLinkInfo &,
const SourceLinkInfo &) {}
void startCodeLine(bool) {}
void endCodeLine() {}
void startCodeAnchor(const char *) {}
void endCodeAnchor() {}
void startFontClass(const char *) {}
void endFontClass() {}
void writeCodeAnchor(const char *) {}
void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
void startCodeFragment(const char *) {}
void endCodeFragment(const char *) {}
// here we are presented with the symbols found by the code parser
void linkableSymbol(int l, const char *sym,Definition *symDef,Definition *context)
{
QCString ctx;
if (context) // the context of the symbol is known
{
if (context->definitionType()==Definition::TypeMember) // it is inside a member
{
Definition *parentContext = context->getOuterScope();
if (parentContext && parentContext->definitionType()==Definition::TypeClass)
// it is inside a member of a class
{
ctx.sprintf("inside %s %s of %s %s",
(dynamic_cast<MemberDef*>(context))->memberTypeName().data(),
context->name().data(),
(dynamic_cast<ClassDef*>(parentContext))->compoundTypeString().data(),
parentContext->name().data());
}
else if (parentContext==Doxygen::globalScope) // it is inside a global member
{
ctx.sprintf("inside %s %s",
(dynamic_cast<MemberDef*>(context))->memberTypeName().data(),
context->name().data());
}
}
if (ctx.isEmpty()) // it is something else (class, or namespace member, ...)
{
ctx.sprintf("in %s",context->name().data());
}
}
printf("Found symbol %s at line %d of %s %s\n",
sym,l,m_fd->getDefFileName().data(),ctx.data());
if (symDef && context) // in this case the definition of the symbol is
// known to doxygen.
{
printf("-> defined at line %d of %s\n",
symDef->getDefLine(),symDef->getDefFileName().data());
}
}
private:
FileDef *m_fd;
};
static void findXRefSymbols(FileDef *fd)
{
// get the interface to a parser that matches the file extension
auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension());
// get the programming language from the file name
SrcLangExt lang = getLanguageFromFileName(fd->name());
// reset the parsers state
intf->resetCodeParserState();
// create a new backend object
XRefDummyCodeGenerator *xrefGen = new XRefDummyCodeGenerator(fd);
// parse the source code
intf->parseCode(*xrefGen,
0,
fileToString(fd->absFilePath()),
lang,
FALSE,
0,
fd);
// dismiss the object.
delete xrefGen;
}
static void listSymbol(Definition *d)
{
if (d!=Doxygen::globalScope && // skip the global namespace symbol
d->name().at(0)!='@' // skip anonymous stuff
)
{
printf("%s\n",
d->name().data());
}
}
static void listSymbols()
{
for (const auto &kv : Doxygen::symbolMap)
{
listSymbol(kv.second);
}
}
static void lookupSymbol(Definition *d)
{
if (d!=Doxygen::globalScope && // skip the global namespace symbol
d->name().at(0)!='@' // skip anonymous stuff
)
{
printf("Symbol info\n");
printf("-----------\n");
printf("Name: %s\n",d->name().data());
printf("File: %s\n",d->getDefFileName().data());
printf("Line: %d\n",d->getDefLine());
// depending on the definition type we can case to the appropriate
// derived to get additional information
switch (d->definitionType())
{
case Definition::TypeClass:
{
ClassDef *cd = dynamic_cast<ClassDef*>(d);
printf("Kind: %s\n",cd->compoundTypeString().data());
}
break;
case Definition::TypeFile:
{
FileDef *fd = dynamic_cast<FileDef*>(d);
printf("Kind: File: #includes %d other files\n",
fd->includeFileList() ? fd->includeFileList()->count() : 0);
}
break;
case Definition::TypeNamespace:
{
NamespaceDef *nd = dynamic_cast<NamespaceDef*>(d);
printf("Kind: Namespace: contains %zu classes and %zu namespaces\n",
nd->getClasses().size(),
nd->getNamespaces().size());
}
break;
case Definition::TypeMember:
{
MemberDef *md = dynamic_cast<MemberDef*>(d);
printf("Kind: %s\n",md->memberTypeName().data());
}
break;
default:
// ignore groups/pages/packages/dirs for now
break;
}
}
}
static void lookupSymbols(const QCString &sym)
{
if (!sym.isEmpty())
{
auto range = Doxygen::symbolMap.find(sym);
bool found=false;
for (auto it=range.first; it!=range.second; ++it)
{
lookupSymbol(it->second);
found=true;
}
if (!found)
{
printf("Unknown symbol\n");
}
}
}
int main(int argc,char **argv)
{
char cmd[256];
int locArgc = argc;
if (locArgc == 2)
{
if (!strcmp(argv[1],"--help"))
{
printf("Usage: %s [source_file | source_dir]\n",argv[0]);
exit(0);
}
else if (!strcmp(argv[1],"--version"))
{
printf("%s version: %s\n",argv[0],getFullVersion());
exit(0);
}
}
if (locArgc!=2)
{
printf("Usage: %s [source_file | source_dir]\n",argv[0]);
exit(1);
}
// initialize data structures
initDoxygen();
// setup the non-default configuration options
checkConfiguration();
adjustConfiguration();
// we need a place to put intermediate files
Config_updateString(OUTPUT_DIRECTORY,"/tmp/doxygen");
// disable html output
Config_updateBool(GENERATE_HTML,FALSE);
// disable latex output
Config_updateBool(GENERATE_LATEX,FALSE);
// be quiet
Config_updateBool(QUIET,TRUE);
// turn off warnings
Config_updateBool(WARNINGS,FALSE);
Config_updateBool(WARN_IF_UNDOCUMENTED,FALSE);
Config_updateBool(WARN_IF_DOC_ERROR,FALSE);
// Extract as much as possible
Config_updateBool(EXTRACT_ALL,TRUE);
Config_updateBool(EXTRACT_STATIC,TRUE);
Config_updateBool(EXTRACT_PRIVATE,TRUE);
Config_updateBool(EXTRACT_LOCAL_METHODS,TRUE);
// Extract source browse information, needed
// to make doxygen gather the cross reference info
Config_updateBool(SOURCE_BROWSER,TRUE);
// In case of a directory take all files on directory and its subdirectories
Config_updateBool(RECURSIVE,TRUE);
// set the input
StringVector inputList;
inputList.push_back(argv[1]);
Config_updateList(INPUT,inputList);
// parse the files
parseInput();
// iterate over the input files
for (const auto &fn : *Doxygen::inputNameLinkedMap)
{
for (const auto &fd : *fn)
{
// get the references (linked and unlinked) found in this file
findXRefSymbols(fd.get());
}
}
// clean up after us
QDir().rmdir("/tmp/doxygen");
while (1)
{
printf("> Type a symbol name or\n> .list for a list of symbols or\n> .quit to exit\n> ");
fgets(cmd,256,stdin);
QCString s(cmd);
if (s.at(s.length()-1)=='\n') s=s.left(s.length()-1); // strip trailing \n
if (s==".list")
listSymbols();
else if (s==".quit")
exit(0);
else
lookupSymbols(s);
}
}

View File

@ -0,0 +1,46 @@
find_package(Iconv)
include_directories(
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/libversion
${GENERATED_SRC}
${PROJECT_SOURCE_DIR}/qtools
${ICONV_INCLUDE_DIR}
${CLANG_INCLUDEDIR}
)
add_executable(doxyparse
doxyparse.cpp
)
add_sanitizers(doxyparse)
if (use_libclang)
if (static_libclang)
set(CLANG_LIBS libclang clangTooling ${llvm_libs})
else()
set(CLANG_LIBS libclang clang-cpp ${llvm_libs})
endif()
if ($ENV{DEB_HOST_ARCH} STREQUAL "armel")
set(EXTRA_CLANG_LIBS atomic)
endif()
endif()
target_link_libraries(doxyparse
doxymain
qtools
md5
lodepng
mscgen
doxygen_version
doxycfg
vhdlparser
${ICONV_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${SQLITE3_LIBRARIES}
${EXTRA_LIBS}
${CLANG_LIBS}
${COVERAGE_LINKER_FLAGS}
${EXTRA_CLANG_LIBS}
)
install(TARGETS doxyparse DESTINATION bin)

52
addon/doxyparse/README.md Normal file
View File

@ -0,0 +1,52 @@
# Doxyparse
This directory contains an "source parsing engine" based on doxyapp code.
Doxyparse modifies the default output of Doxygen and dumps the dependencies
among code elements in a YAML format, instead of output it in a human-readable
format, as Doxygen does Doxyparse's output is intended to produce a
machine-readable output.
Doxyparse has been used in many software engineering research (as a source-code
static analysis tool) regards on software metrics, quality metrics and so on,
Doxyparse was first used by the [Analizo](http://analizo.org) toolkit, a suite
of source code analysis tools, aimed at being language-independent and
extensible, able to extract and calculate a fair number of source code metrics,
generate dependency graphs, and other software evolution analysis.
Academic publications citing Doxyparse:
* https://scholar.google.com.br/scholar?q=doxyparse
## build dependencies
apt-get install flex bison cmake build-essential python
## build
cmake -G "Unix Makefiles" -Dbuild_parse=ON
make
## install
sudo make install
## release
* ensure analizo testsuite passing on newer doxyparse version
* update debian/changelog, commit, push
* create git tag, push to github analizo/doxyparse
* build on amd64 and i386 archs, upload tar.gz to github
* tar -zcf doxyparse_<VERSION>_amd64.tar.gz -C bin/ doxyparse
* tar -zcf doxyparse_<VERSION>_i386.tar.gz -C bin/ doxyparse
* build debian packages for amd64 and i386, update analizo.org repository
* (see analizo.github.io/README.md file for updating repository instructions)
* upload the deb files to github release tag also
* check if a alien-doxyparse release is necessary and do it on cpan
## Authors
* Antonio Terceiro <terceiro@softwarelivre.org>
* João M. Miranda <joaomm88@gmail.com>
* Joenio Costa <joenio@joenio.me>
* Paulo Meirelles <paulo@softwarelivre.org>
* Vinicius Daros <vkdaros@mercurio.eclipse.ime.usp.br>

View File

@ -0,0 +1,10 @@
.TH DOXYPARSE "1" "DATE" "doxyparse VERSION" "User Commands"
.SH NAME
doxyparse \- parse and dumps information about the code
.SH SYNOPSIS
.B doxyparse
[\fIsource file\fR...]
.SH DESCRIPTION
Parses source code and dumps the dependencies between the code elements.
.SH SEE ALSO
doxygen(1), doxytag(1), doxywizard(1).

View File

@ -0,0 +1,544 @@
/******************************************************************************
*
* Copyright (C) 2009-2015 by Joenio Costa.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
/** @file
* @brief Code parse based on doxyapp by Dimitri van Heesch
*
*/
#include <stdlib.h>
#if !defined(_WIN32) || defined(__CYGWIN__)
#include <unistd.h>
#else
#include <windows.h>
#endif
#include "version.h"
#include "doxygen.h"
#include "outputgen.h"
#include "parserintf.h"
#include "classlist.h"
#include "config.h"
#include "filedef.h"
#include "util.h"
#include "filename.h"
#include "arguments.h"
#include "memberlist.h"
#include "types.h"
#include <string>
#include <cstdlib>
#include <sstream>
#include <map>
#include <qdir.h>
#include <qcstring.h>
#include <qregexp.h>
#include "namespacedef.h"
#include "portable.h"
class Doxyparse : public CodeOutputInterface
{
public:
Doxyparse(const FileDef *fd) : m_fd(fd) {}
~Doxyparse() {}
// these are just null functions, they can be used to produce a syntax highlighted
// and cross-linked version of the source code, but who needs that anyway ;-)
void codify(const char *) {}
void writeCodeLink(const char *,const char *,const char *,const char *,const char *) {}
void startCodeLine() {}
void endCodeLine() {}
void startCodeAnchor(const char *) {}
void endCodeAnchor() {}
void startFontClass(const char *) {}
void endFontClass() {}
void writeCodeAnchor(const char *) {}
void writeLineNumber(const char *,const char *,const char *,int) {}
virtual void writeTooltip(const char *,const DocLinkInfo &,
const char *,const char *,const SourceLinkInfo &,
const SourceLinkInfo &) {}
void startCodeLine(bool) {}
void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
void startCodeFragment(const char *) {}
void endCodeFragment(const char *) {}
void linkableSymbol(int l, const char *sym, Definition *symDef, Definition *context)
{
if (!symDef) {
// in this case we have a local or external symbol
// TODO record use of external symbols
// TODO must have a way to differentiate external symbols from local variables
}
}
private:
const FileDef *m_fd;
};
static bool is_c_code = true;
static void findXRefSymbols(FileDef *fd)
{
// get the interface to a parser that matches the file extension
auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension());
// get the programming language from the file name
SrcLangExt lang = getLanguageFromFileName(fd->name());
// reset the parsers state
intf->resetCodeParserState();
// create a new backend object
Doxyparse *parse = new Doxyparse(fd);
// parse the source code
intf->parseCode(*parse, 0, fileToString(fd->absFilePath()), lang, FALSE, 0, fd);
// dismiss the object.
delete parse;
}
static bool ignoreStaticExternalCall(const MemberDef *context, const MemberDef *md) {
if (md->isStatic()) {
if(md->getFileDef() && context->getFileDef()) {
if(md->getFileDef()->getOutputFileBase() == context->getFileDef()->getOutputFileBase())
// TODO ignore prefix of file
return false;
else
return true;
}
else {
return false;
}
}
else {
return false;
}
}
static void startYamlDocument() {
printf("---\n");
}
static void printFile(std::string file) {
printf("%s:\n", file.c_str());
}
static void printModule(std::string module) {
printf(" \"%s\":\n", unescapeCharsInString(module.c_str()).data());
}
static void printClassInformation(std::string information) {
printf(" information: %s\n", information.c_str());
}
static void printInherits() {
printf(" inherits:\n");
}
static void printInheritance(std::string base_class) {
printf(" - \"%s\"\n", base_class.c_str());
}
static void printDefines() {
printf(" defines:\n");
}
static void printDefinition(std::string type, std::string signature, int line) {
printf(" - \"%s\":\n", signature.substr(0, 1022).c_str());
printf(" type: %s\n", type.c_str());
printf(" line: %d\n", line);
}
static void printProtection(std::string protection) {
printf(" protection: %s\n", protection.c_str());
}
static void printPrototypeYes() {
printf(" prototype: yes\n");
}
static void printNumberOfLines(int lines) {
printf(" lines_of_code: %d\n", lines);
}
static void printNumberOfArguments(size_t arguments) {
printf(" parameters: %zu\n", arguments);
}
static void printUses() {
printf(" uses:\n");
}
static void printReferenceTo(std::string type, std::string signature, std::string defined_in) {
printf(" - \"%s\":\n", signature.substr(0, 1022).c_str());
printf(" type: %s\n", type.c_str());
printf(" defined_in: \"%s\"\n", unescapeCharsInString(defined_in.c_str()).data());
}
static void printNumberOfConditionalPaths(const MemberDef* md) {
printf(" conditional_paths: %d\n", md->numberOfFlowKeyWords());
}
static int isPartOfCStruct(const MemberDef * md) {
return is_c_code && md->getClassDef() != NULL;
}
std::string sanitizeString(std::string data) {
QCString new_data = QCString(data.c_str());
new_data.replace(QRegExp("\""), "");
new_data.replace(QRegExp("\\"), ""); // https://github.com/analizo/analizo/issues/138
return !new_data.isEmpty() ? new_data.data() : "";
}
std::string argumentData(const Argument &argument) {
std::string data = "";
if (argument.type.size() > 1)
data = sanitizeString(argument.type.data());
else if (!argument.name.isEmpty())
data = sanitizeString(argument.name.data());
return data;
}
std::string functionSignature(const MemberDef* md) {
std::string signature = sanitizeString(md->name().data());
if(md->isFunction()){
const ArgumentList &argList = md->argumentList();
signature += "(";
auto it = argList.begin();
if(it!=argList.end()) {
signature += argumentData(*it);
for(++it; it!=argList.end(); ++it) {
signature += std::string(",") + argumentData(*it);
}
}
signature += ")";
}
return signature;
}
static void referenceTo(const MemberDef* md) {
std::string type = md->memberTypeName().data();
std::string defined_in = "";
std::string signature = "";
if (isPartOfCStruct(md)) {
signature = md->getClassDef()->name().data() + std::string("::") + functionSignature(md);
defined_in = md->getClassDef()->getFileDef()->getOutputFileBase().data();
}
else {
signature = functionSignature(md);
if (md->getClassDef()) {
defined_in = md->getClassDef()->name().data();
}
else if (md->getFileDef()) {
defined_in = md->getFileDef()->getOutputFileBase().data();
}
else if (md->getNamespaceDef()) {
defined_in = md->getNamespaceDef()->name().data();
}
}
printReferenceTo(type, signature, defined_in);
}
void protectionInformation(Protection protection) {
if (protection == Public) {
printProtection("public");
}
else if (protection == Protected) {
printProtection("protected");
}
else if (protection == Private) {
printProtection("private");
}
else if (protection == Package) {
printProtection("package");
}
}
void cModule(const ClassDef* cd) {
const MemberList* ml = cd->getMemberList(MemberListType_variableMembers);
if (ml) {
const FileDef *fd = cd->getFileDef();
const MemberList *fd_ml = fd->getMemberList(MemberListType_allMembersList);
if (!fd_ml || fd_ml->count() == 0) {
printModule(fd->getOutputFileBase().data());
printDefines();
}
MemberListIterator mli(*ml);
const MemberDef* md;
for (mli.toFirst(); (md=mli.current()); ++mli) {
printDefinition("variable", cd->name().data() + std::string("::") + md->name().data(), md->getDefLine());
protectionInformation(md->protection());
}
}
}
static bool checkOverrideArg(const ArgumentList &argList, const MemberDef *md) {
if(!md->isFunction() || argList.empty()){
return false;
}
for (const Argument &argument : argList) {
if(md->name() == argument.name) {
return true;
}
}
return false;
}
void functionInformation(const MemberDef* md) {
std::string temp = "";
int size = md->getEndBodyLine() - md->getStartBodyLine() + 1;
printNumberOfLines(size);
const ArgumentList &argList = md->argumentList();
if (!argList.empty())
{
temp = argumentData(argList.front());
// TODO: This is a workaround; better not include "void" in argList, in the first place.
if (temp!="void")
{
printNumberOfArguments(argList.size());
}
}
printNumberOfConditionalPaths(md);
auto refList = md->getReferencesMembers();
if (!refList.empty()) {
printUses();
for (const auto &rmd : refList) {
if (rmd->definitionType() == Definition::TypeMember && !ignoreStaticExternalCall(md, rmd) && !checkOverrideArg(argList, rmd)) {
referenceTo(rmd);
}
}
}
}
void prototypeInformation(const MemberDef* md) {
printPrototypeYes();
const ArgumentList &argList = md->argumentList();
printNumberOfArguments(argList.size());
}
static void lookupSymbol(const Definition *d) {
if (d->definitionType() == Definition::TypeMember) {
const MemberDef *md = dynamic_cast<const MemberDef*>(d);
std::string type = md->memberTypeName().data();
std::string signature = functionSignature(md);
printDefinition(type, signature, md->getDefLine());
protectionInformation(md->protection());
if (md->isFunction() && md->isPrototype()) {
prototypeInformation(md);
}
else if (md->isFunction()) {
functionInformation(md);
}
}
}
void listMembers(const MemberList *ml) {
if (ml) {
MemberListIterator mli(*ml);
const MemberDef *md;
for (mli.toFirst(); (md=mli.current()); ++mli) {
lookupSymbol((Definition*) md);
}
}
}
void listAllMembers(const ClassDef* cd) {
// methods
listMembers(cd->getMemberList(MemberListType_functionMembers));
// constructors
listMembers(cd->getMemberList(MemberListType_constructors));
// attributes
listMembers(cd->getMemberList(MemberListType_variableMembers));
}
static void classInformation(const ClassDef* cd) {
if (is_c_code) {
cModule(cd);
} else {
printModule(cd->name().data());
if (!cd->baseClasses().empty()) {
printInherits();
for (const auto &bcd : cd->baseClasses()) {
printInheritance(sanitizeString(bcd.classDef->name().data()));
}
}
if(cd->isAbstract()) {
printClassInformation("abstract class");
}
printDefines();
listAllMembers(cd);
}
}
static bool checkLanguage(std::string& filename, std::string extension) {
if (filename.find(extension, filename.size() - extension.size()) != std::string::npos) {
return true;
} else {
return false;
}
}
/* Detects the programming language of the project. Actually, we only care
* about whether it is a C project or not. */
static void detectProgrammingLanguage(FileNameLinkedMap &fnli) {
for (const auto &fn : fnli) {
std::string filename = fn->fileName();
if (
checkLanguage(filename, ".cc") ||
checkLanguage(filename, ".cxx") ||
checkLanguage(filename, ".cpp") ||
checkLanguage(filename, ".java") ||
checkLanguage(filename, ".py") ||
checkLanguage(filename, ".pyw") ||
checkLanguage(filename, ".cs")
) {
is_c_code = false;
}
}
}
static void listSymbols() {
detectProgrammingLanguage(*Doxygen::inputNameLinkedMap);
// iterate over the input files
for (const auto &fn : *Doxygen::inputNameLinkedMap) {
for (const auto &fd : *fn) {
printFile(fd->absFilePath().data());
MemberList *ml = fd->getMemberList(MemberListType_allMembersList);
if (ml && ml->count() > 0) {
printModule(fd->getOutputFileBase().data());
printDefines();
listMembers(ml);
}
ClassDefSet visitedClasses;
for (const auto &cd : fd->getClasses()) {
if (visitedClasses.find(cd)==visitedClasses.end()) {
classInformation(cd);
visitedClasses.insert(cd);
}
}
}
}
// TODO print external symbols referenced
}
int main(int argc,char **argv) {
int locArgc = argc;
if (locArgc == 2)
{
if (!strcmp(argv[1],"--help"))
{
printf("Usage: %s [source_file | source_dir]\n",argv[0]);
exit(0);
}
else if (!strcmp(argv[1],"--version"))
{
printf("%s version: %s\n",argv[0],getFullVersion());
exit(0);
}
}
if (locArgc!=2)
{
printf("Usage: %s [source_file | source_dir]\n",argv[0]);
exit(1);
}
// initialize data structures
initDoxygen();
// check and finalize the configuration
checkConfiguration();
adjustConfiguration();
// setup the non-default configuration options
// we need a place to put intermediate files
std::ostringstream tmpdir;
unsigned int pid = Portable::pid();
if (Portable::getenv("TMP"))
tmpdir << Portable::getenv("TMP") << "/doxyparse-" << pid;
else if (Portable::getenv("TEMP"))
tmpdir << Portable::getenv("TEMP") << "/doxyparse-" << pid;
else
tmpdir << "doxyparse-" << pid;
Config_updateString(OUTPUT_DIRECTORY,tmpdir.str().c_str());
// enable HTML (fake) output to omit warning about missing output format
Config_updateBool(GENERATE_HTML,TRUE);
// disable latex output
Config_updateBool(GENERATE_LATEX,FALSE);
// be quiet
Config_updateBool(QUIET,TRUE);
// turn off warnings
Config_updateBool(WARNINGS,FALSE);
Config_updateBool(WARN_IF_UNDOCUMENTED,FALSE);
Config_updateBool(WARN_IF_DOC_ERROR,FALSE);
// Extract as much as possible
Config_updateBool(EXTRACT_ALL,TRUE);
Config_updateBool(EXTRACT_STATIC,TRUE);
Config_updateBool(EXTRACT_PRIVATE,TRUE);
Config_updateBool(EXTRACT_LOCAL_METHODS,TRUE);
Config_updateBool(EXTRACT_PACKAGE,TRUE);
// Extract source browse information, needed
// to make doxygen gather the cross reference info
Config_updateBool(SOURCE_BROWSER,TRUE);
// find functions call between modules
Config_updateBool(CALL_GRAPH,TRUE);
// loop recursive over input files
Config_updateBool(RECURSIVE,TRUE);
// add file extensions
Config_updateList(FILE_PATTERNS, { "*.cc", "*.cxx", "*.cpp", "*.java",
"*.py", "*.pyw", "*.cs", "*.c", "*.h", "*.hh", "*.hpp"});
// set the input
StringVector inputList;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-") == 0) {
char filename[1024];
while (1) {
scanf("%s[^\n]", filename);
if (feof(stdin)) {
break;
}
inputList.push_back(filename);
}
} else {
inputList.push_back(argv[i]);
}
}
Config_updateList(INPUT,inputList);
if (inputList.empty()) {
exit(0);
}
// parse the files
parseInput();
// iterate over the input files
for (const auto &fn : *Doxygen::inputNameLinkedMap) {
for (const auto &fd : *fn) {
// get the references (linked and unlinked) found in this file
findXRefSymbols(fd.get());
}
}
QDir thisDir;
// remove temporary files
if (!Doxygen::filterDBFileName.isEmpty()) thisDir.remove(Doxygen::filterDBFileName);
// clean up after us
thisDir.rmdir(Config_getString(OUTPUT_DIRECTORY));
startYamlDocument();
listSymbols();
std::string cleanup_command = "rm -rf ";
cleanup_command += tmpdir.str();
system(cleanup_command.c_str());
exit(0);
}

397
addon/doxypysql/search.py Executable file
View File

@ -0,0 +1,397 @@
#!/usr/bin/python
# python script to search through doxygen_sqlite3.db
#
# Permission to use, copy, modify, and distribute this software and its
# documentation under the terms of the GNU General Public License is hereby
# granted. No representations are made about the suitability of this software
# for any purpose. It is provided "as is" without express or implied warranty.
# See the GNU General Public License for more details.
#
import sqlite3
import sys
import os
import getopt
import json
import re
class MemberType:
Define="macro definition"
Function="function"
Variable="variable"
Typedef="typedef"
Enumeration="enumeration"
EnumValue="enumvalue"
Signal="signal"
Slot="slot"
Friend="friend"
DCOP="dcop"
Property="property"
Event="event"
File="file"
class RequestType:
References="9901"
Struct="9902"
Includers="9903"
Includees="9904"
Members="9905"
BaseClasses="9906"
SubClasses="9907"
g_use_regexp=False
###############################################################################
# case-insensitive sqlite regexp function
def re_fn(expr, item):
reg = re.compile(expr, re.I)
return reg.search(item) is not None
def openDb(dbname):
if dbname == None:
dbname = "doxygen_sqlite3.db"
if not os.path.isfile(dbname):
raise BaseException("No such file %s" % dbname )
conn = sqlite3.connect(dbname)
conn.execute('PRAGMA temp_store = MEMORY;')
conn.row_factory = sqlite3.Row
conn.create_function("REGEXP", 2, re_fn)
return conn
###############################################################################
class Finder:
def __init__(self,cn,name,row_type=str):
self.cn=cn
self.name=name
self.row_type=row_type
def match(self,row):
if self.row_type is int:
return " rowid=?"
else:
if g_use_regexp == True:
return " REGEXP (?,%s)" %row
else:
return " %s=?" %row
def fileName(self,file_id):
if self.cn.execute("SELECT COUNT(*) FROM path WHERE rowid=?",[file_id]).fetchone()[0] > 1:
sys.stderr.write("WARNING: non-uniq fileid [%s]. Considering only the first match." % file_id)
for r in self.cn.execute("SELECT * FROM path WHERE rowid=?",[file_id]).fetchall():
return r['name']
return ""
def fileId(self,name):
if self.cn.execute("SELECT COUNT(*) FROM path WHERE"+self.match("name"),[name]).fetchone()[0] > 1:
sys.stderr.write("WARNING: non-uniq file name [%s]. Considering only the first match." % name)
for r in self.cn.execute("SELECT rowid FROM path WHERE"+self.match("name"),[name]).fetchall():
return r[0]
return -1
###############################################################################
def references(self):
o=[]
cur = self.cn.cursor()
cur.execute("SELECT rowid FROM memberdef WHERE"+self.match("name"),[self.name])
rowids = cur.fetchall()
if len(rowids) == 0:
return o
rowid = rowids[0]['rowid']
cur = self.cn.cursor()
#TODO:SELECT rowid from refid where refid=refid
for info in cur.execute("SELECT * FROM xrefs WHERE dst_rowid=?", [rowid]):
item={}
cur = self.cn.cursor()
for i2 in cur.execute("SELECT * FROM memberdef WHERE rowid=?",[info['src_rowid']]):
item['name']=i2['name']
item['src']=info['src_rowid']
# Below no longer directly supported on this entry; can be found from either memberdef
#item['file']=self.fileName(info['file_id'])
#item['line']=info['line']
o.append(item)
return o
###############################################################################
def function(self):
o=[]
c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Function])
for r in c.fetchall():
item={}
item['name'] = r['name']
item['definition'] = r['definition']
item['argsstring'] = r['argsstring']
item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
item['detaileddescription'] = r['detaileddescription']
o.append(item)
return o
###############################################################################
def file(self):
o=[]
for r in self.cn.execute("SELECT rowid,name FROM local_file WHERE"+self.match("name"),[self.name]).fetchall():
item={}
item['name'] = r['name']
item['id'] = r['rowid']
o.append(item)
return o
###############################################################################
def macro(self):
o=[]
c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Define])
for r in c.fetchall():
item={}
item['name'] = r['name']
if r['argsstring']:
item['argsstring'] = r['argsstring']
item['definition'] = r['initializer']
item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
o.append(item)
return o
###############################################################################
def typedef(self):
o=[]
c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Typedef])
for r in c.fetchall():
item={}
item['name'] = r['name']
item['definition'] = r['definition']
item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
o.append(item)
return o
###############################################################################
def variable(self):
o=[]
c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Variable])
for r in c.fetchall():
item={}
item['name'] = r['name']
item['definition'] = r['definition']
item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
o.append(item)
return o
###############################################################################
def params(self):
o=[]
c=self.cn.execute('SELECT rowid FROM memberdef WHERE'+self.match("name"),[self.name])
for r in c.fetchall():
#a=("SELECT * FROM param where id=(SELECT param_id FROM memberdef_param where memberdef_id=?",[memberdef_id])
item={}
item['id'] = r['id']
o.append(item)
return o
###############################################################################
def struct(self):
o=[]
c=self.cn.execute('SELECT * FROM compounddef WHERE'+self.match("name"),[self.name])
for r in c.fetchall():
item={}
item['name'] = r['name']
o.append(item)
return o
###############################################################################
def includers(self):
o=[]
fid = self.fileId(self.name)
c=self.cn.execute('SELECT * FROM includes WHERE dst_id=?',[fid])
for r in c.fetchall():
item={}
item['name'] = self.fileName(r['src_id'])
o.append(item)
return o
###############################################################################
def includees(self):
o=[]
fid = self.fileId(self.name)
c=self.cn.execute('SELECT * FROM includes WHERE src_id=?',[fid])
for r in c.fetchall():
item={}
item['name'] = self.fileName(r['dst_id'])
o.append(item)
return o
###############################################################################
def members(self):
o=[]
c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("scope"),[self.name])
for r in c.fetchall():
item={}
item['name'] = r['name']
item['definition'] = r['definition']
item['argsstring'] = r['argsstring']
item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
#item['documentation'] = r['documentation']
o.append(item)
return o
###############################################################################
def baseClasses(self):
o=[]
c=self.cn.execute('SELECT compounddef.name FROM compounddef JOIN compoundref ON compounddef.rowid=compoundref.base_rowid WHERE compoundref.derived_rowid IN (SELECT rowid FROM compounddef WHERE'+self.match("name")+')',[self.name])
for r in c.fetchall():
item={}
item['name'] = r['name']
o.append(item)
return o
###############################################################################
def subClasses(self):
o=[]
c=self.cn.execute('SELECT compounddef.name FROM compounddef JOIN compoundref ON compounddef.rowid=compoundref.derived_rowid WHERE compoundref.base_rowid IN (SELECT rowid FROM compounddef WHERE'+self.match("name")+')',[self.name])
for r in c.fetchall():
item={}
item['name'] = r['name']
o.append(item)
return o
###############################################################################
def process(f,kind):
request_processors = {
MemberType.Function: f.function,
MemberType.File: f.file,
MemberType.Define: f.macro,
MemberType.Variable: f.variable,
MemberType.Typedef: f.typedef,
RequestType.References: f.references,
RequestType.Struct: f.struct,
RequestType.Includers: f.includers,
RequestType.Includees: f.includees,
RequestType.Members: f.members,
RequestType.BaseClasses: f.baseClasses,
RequestType.SubClasses: f.subClasses
}
return request_processors[kind]()
###############################################################################
# the -H option isn't documented. It's one of the more recent additions, but it's treating refids as if they would be a string. I'm just taking a stab at updating it for now, converting to use rowid, and making other edits necessary to get it to run.
def processHref(cn,ref):
j={}
# is it in memberdef ?
table="memberdef"
if ( cn.execute("SELECT count(*) from %s WHERE rowid=?"%table,[ref] ).fetchone()[0] > 0 ):
for r in cn.execute("SELECT kind,rowid FROM %s WHERE rowid=?" % table,[ref]).fetchall():
f=Finder(cn,r['rowid'],int)
j=process(f,str(r['kind']))
# is it in compounddef ?
table="compounddef"
if ( cn.execute("SELECT count(*) from %s WHERE rowid=?"%table,[ref]).fetchone()[0] > 0 ):
for r in cn.execute("SELECT rowid FROM %s WHERE rowid=?"%table,[ref] ).fetchall():
f=Finder(cn,r[0],int)
j=process(f,RequestType.Struct)
return j
###############################################################################
def serveCgi():
import cgi
print('Content-Type: application/json\n')
fieldStorage = cgi.FieldStorage()
form = dict((key, fieldStorage.getvalue(key)) for key in fieldStorage.keys())
if 'href' in form:
ref = form['href']
else:
print('{"result": null, "error": "no refid given"}')
sys.exit(0)
cn=openDb('doxygen_sqlite3.db')
j = processHref(cn,ref)
print(json.dumps({"result":j,"error":None}))
###############################################################################
def usage():
sys.stderr.write("""Usage: search.py [Options]
Options:
-h, --help
-d <D> Use database <D> for queries.
-f <F> Search for definition of function <F>.
-m <M> Search for definition of macro <M>.
-r <F> Search for references to function <F>.
-t <T> Search for definition of type <T>.
-v <V> Search for definition of variable <V>.
-I <I> What files are including <I>.
-i <i> What files are included by <i>.
-B <C> Get the base classes of class <C>.
-M <C> Get all members of class <C>.
-S <C> Get the sub classes of class <C>.
-R Consider the search <term> to be a regex.
""")
###############################################################################
def serveCli(argv):
try:
opts, args = getopt.getopt(argv, "hr:RI:i:d:f:m:t:v:H:M:B:S:F:",["help"])
except getopt.GetoptError:
usage()
sys.exit(1)
ref=None
dbname=None
j={}
global g_use_regexp
for a, o in opts:
if a in ('-h', '--help'):
usage()
sys.exit(0)
elif a in ('-d'):
dbname=o
continue
elif a in ('-r'):
kind=RequestType.References
elif a in ('-R'):
g_use_regexp=True
continue
elif a in ('-I'):
kind=RequestType.Includers
elif a in ('-i'):
kind=RequestType.Includees
elif a in ('-M'):
kind=RequestType.Members
elif a in ('-B'):
kind=RequestType.BaseClasses
elif a in ('-S'):
kind=RequestType.SubClasses
elif a in ('-f'):
kind=MemberType.Function
elif a in ('-F'):
# undocumented
# seems to fit with the lower case "search" patterns?
kind=MemberType.File
elif a in ('-m'):
kind=MemberType.Define
elif a in ('-t'):
kind=MemberType.Typedef
elif a in ('-v'):
kind=MemberType.Variable
elif a in ('-H'):
# undocumented
ref = o
cn=openDb(dbname)
f=Finder(cn,o)
if ref != None:
j=processHref(cn,ref)
else:
j=process(f,kind)
print(json.dumps(j,indent=4))
def main(argv):
if 'REQUEST_METHOD' in os.environ:
serveCgi()
else:
serveCli(argv)
if __name__ == '__main__':
main(sys.argv[1:])

View File

@ -0,0 +1,36 @@
find_package(xapian REQUIRED)
find_package(ZLIB REQUIRED)
if (WIN32)
set(WIN_EXTRA_LIBS uuid.lib rpcrt4.lib ws2_32.lib)
endif()
include_directories(
${PROJECT_SOURCE_DIR}/libversion
${PROJECT_SOURCE_DIR}/qtools
${XAPIAN_INCLUDE_DIR}
${ZLIB_INCLUDE_DIRS}
)
add_executable(doxyindexer
doxyindexer.cpp
)
target_link_libraries(doxyindexer
${XAPIAN_LIBRARIES}
${ZLIB_LIBRARIES}
${WIN_EXTRA_LIBS}
${COVERAGE_LINKER_FLAGS}
doxygen_version
qtools
)
add_executable(doxysearch.cgi
doxysearch.cpp
)
target_link_libraries(doxysearch.cgi
doxygen_version
${XAPIAN_LIBRARIES}
${ZLIB_LIBRARIES}
${WIN_EXTRA_LIBS}
)
install(TARGETS doxyindexer doxysearch.cgi DESTINATION bin)

View File

@ -0,0 +1,391 @@
/******************************************************************************
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
// STL includes
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>
// Qtools includes
#include <qregexp.h>
#include <qxml.h>
#include <qfile.h>
#include <qfileinfo.h>
// Xapian include
#include <xapian.h>
#include "version.h"
#define MAX_TERM_LENGTH 245
#if defined(_WIN32) && !defined(__CYGWIN__)
static char pathSep = '\\';
#else
static char pathSep = '/';
#endif
static void safeAddTerm(const std::string &term,Xapian::Document &doc,int wfd)
{
if (term.length()<=MAX_TERM_LENGTH) doc.add_term(term,wfd);
}
/** trims \a whitespace characters from the start and end of string \a str. */
static std::string trim(const std::string& str,
const std::string& whitespace = " \t")
{
size_t strBegin = str.find_first_not_of(whitespace);
if (strBegin == std::string::npos)
return ""; // no content
size_t strEnd = str.find_last_not_of(whitespace);
size_t strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
/** trims \a whitespace from start and end and replace occurrences of
* \a whitespace with \a fill.
*/
static std::string reduce(const std::string& str,
const std::string& fill = " ",
const std::string& whitespace = " \t")
{
// trim first
std::string result = trim(str, whitespace);
// replace sub ranges
size_t beginSpace = result.find_first_of(whitespace);
while (beginSpace != std::string::npos)
{
size_t endSpace = result.find_first_not_of(whitespace, beginSpace);
size_t range = endSpace - beginSpace;
result.replace(beginSpace, range, fill);
size_t newStart = beginSpace + fill.length();
beginSpace = result.find_first_of(whitespace, newStart);
}
return result;
}
/** Adds all words in \a s to document \a doc with weight \a wfd */
static void addWords(const std::string &s,Xapian::Document &doc,int wfd)
{
std::istringstream iss(s);
std::istream_iterator<std::string> begin(iss),end,it;
for (it=begin;it!=end;++it)
{
std::string word = *it;
std::string lword = word;
std::transform(lword.begin(), lword.end(), lword.begin(), ::tolower);
safeAddTerm(word,doc,wfd);
if (lword!=word)
{
safeAddTerm(lword,doc,wfd);
}
}
}
/** Adds all identifiers in \a s to document \a doc with weight \a wfd */
static void addIdentifiers(const std::string &s,Xapian::Document &doc,int wfd)
{
QRegExp re("[A-Z_a-z][A-Z_a-z0-9]*");
int i,l,p=0;
QCString qs = s.c_str();
while ((i=re.match(qs,p,&l))!=-1)
{
safeAddTerm(qs.mid(p,i-p).data(),doc,wfd);
p=i+l;
}
}
/** Replaces all occurrences of \a old with \a repl in string \a str */
static void replace_all(std::string& str, const std::string& old, const std::string& repl)
{
size_t pos = 0;
while ((pos = str.find(old, pos)) != std::string::npos)
{
str.replace(pos, old.length(), repl);
pos += repl.length();
}
}
/** Replaces all XML entities in \a s with their unescaped representation */
static std::string unescapeXmlEntities(const std::string &s)
{
std::string result=s;
replace_all(result,"&gt;",">");
replace_all(result,"&lt;","<");
replace_all(result,"&apos;","'");
replace_all(result,"&quot;","\"");
replace_all(result,"&amp;","&");
return result;
}
/** This class is a wrapper around SAX style XML parser, which
* parses the file without first building a DOM tree in memory.
*/
class XMLContentHandler : public QXmlDefaultHandler
{
public:
/** Handler for parsing XML data */
XMLContentHandler(const QString &path)
: m_db((path+"doxysearch.db").utf8().data(),Xapian::DB_CREATE_OR_OVERWRITE),
m_stemmer("english")
{
m_curFieldName = UnknownField;
m_indexer.set_stemmer(m_stemmer);
m_indexer.set_document(m_doc);
}
/** Free data handler */
~XMLContentHandler()
{
m_db.commit();
}
private:
enum FieldNames
{
UnknownField = 0,
TypeField = 1,
NameField = 2,
ArgsField = 3,
TagField = 4,
UrlField = 5,
KeywordField = 6,
TextField = 7
};
/** Handler for a start tag. Called for <doc> and <field> tags */
bool startElement(const QString &, const QString &,
const QString &name, const QXmlAttributes &attrib)
{
m_data="";
if (name=="field")
{
QString fieldName = attrib.value("name");
if (fieldName=="type") m_curFieldName=TypeField;
else if (fieldName=="name") m_curFieldName=NameField;
else if (fieldName=="args") m_curFieldName=ArgsField;
else if (fieldName=="tag") m_curFieldName=TagField;
else if (fieldName=="url") m_curFieldName=UrlField;
else if (fieldName=="keywords") m_curFieldName=KeywordField;
else if (fieldName=="text") m_curFieldName=TextField;
else m_curFieldName=UnknownField;
}
return TRUE;
}
/** Handler for an end tag. Called for </doc> and </field> tags */
bool endElement(const QString &, const QString &, const QString &name)
{
if (name=="doc") // </doc>
{
std::string term = m_doc.get_value(NameField);
std::string partTerm;
size_t pos = term.rfind("::");
if (pos!=std::string::npos)
{
partTerm = term.substr(pos+2);
}
if (m_doc.get_value(TypeField)=="class" ||
m_doc.get_value(TypeField)=="file" ||
m_doc.get_value(TypeField)=="namespace") // containers get highest prio
{
safeAddTerm(term,m_doc,1000);
if (!partTerm.empty())
{
safeAddTerm(partTerm,m_doc,500);
}
}
else // members and others get lower prio
{
safeAddTerm(m_doc.get_value(NameField),m_doc,100);
if (!partTerm.empty())
{
safeAddTerm(partTerm,m_doc,50);
}
}
m_db.add_document(m_doc);
m_doc.clear_values();
m_doc.clear_terms();
}
else if (name=="field" && m_curFieldName!=UnknownField) // </field>
{
// strip whitespace from m_data
m_data = reduce(m_data);
// replace XML entities
m_data = unescapeXmlEntities(m_data);
// add data to the document
m_doc.add_value(m_curFieldName,m_data);
switch (m_curFieldName)
{
case TypeField:
case NameField:
case TagField:
case UrlField:
// meta data that is not searchable
break;
case KeywordField:
addWords(m_data,m_doc,50);
break;
case ArgsField:
addIdentifiers(m_data,m_doc,10);
break;
case TextField:
addWords(m_data,m_doc,2);
break;
default:
break;
}
m_data="";
m_curFieldName=UnknownField;
}
// reset m_data
return TRUE;
}
/** Handler for inline text */
bool characters(const QString& ch)
{
m_data += std::string(ch.utf8());
return TRUE;
}
// internal state
Xapian::WritableDatabase m_db;
Xapian::Document m_doc;
Xapian::TermGenerator m_indexer;
Xapian::Stem m_stemmer;
std::string m_data;
FieldNames m_curFieldName;
};
/** Class for handling error during XML parsing */
class XMLErrorHandler : public QXmlErrorHandler
{
public:
virtual ~XMLErrorHandler() {}
bool warning( const QXmlParseException & )
{
return FALSE;
}
bool error( const QXmlParseException & )
{
return FALSE;
}
bool fatalError( const QXmlParseException &exception )
{
std::cerr << "Fatal error at line " << exception.lineNumber()
<< " column " << exception.columnNumber() << ": "
<< exception.message().utf8() << std::endl;
return FALSE;
}
QString errorString() { return ""; }
private:
QString errorMsg;
};
static void usage(const char *name, int exitVal = 1)
{
std::cerr << "Usage: " << name << " [-o output_dir] searchdata.xml [searchdata2.xml ...]" << std::endl;
exit(exitVal);
}
/** main function to index data */
int main(int argc,const char **argv)
{
if (argc<2)
{
usage(argv[0]);
}
QString outputDir;
for (int i=1;i<argc;i++)
{
if (std::string(argv[i])=="-o")
{
if (i>=argc-1)
{
std::cerr << "Error: missing parameter for -o option" << std::endl;
usage(argv[0]);
}
else
{
i++;
outputDir=argv[i];
QFileInfo fi(outputDir);
if (!fi.exists() || !fi.isDir())
{
std::cerr << "Error: specified output directory does not exist!" << std::endl;
usage(argv[0]);
}
}
}
else if (std::string(argv[i])=="-h" || std::string(argv[i])=="--help")
{
usage(argv[0],0);
}
else if (std::string(argv[i])=="-v" || std::string(argv[i])=="--version")
{
std::cerr << argv[0] << " version: " << getFullVersion() << std::endl;
exit(0);
}
}
try
{
if (!outputDir.isEmpty() && outputDir.at(outputDir.length()-1)!=pathSep)
{
outputDir+=pathSep;
}
XMLContentHandler handler(outputDir);
XMLErrorHandler errorHandler;
for (int i=1;i<argc;i++)
{
if (std::string(argv[i])=="-o")
{
i++;
}
else
{
QString xmlFileName = argv[i];
std::cout << "Processing " << xmlFileName.utf8() << "..." << std::endl;
QFile xmlFile(xmlFileName);
QXmlInputSource source(xmlFile);
QXmlSimpleReader reader;
reader.setContentHandler(&handler);
reader.setErrorHandler(&errorHandler);
reader.parse(source);
}
}
}
catch(const Xapian::Error &e)
{
std::cerr << "Caught exception: " << e.get_description() << std::endl;
}
catch(...)
{
std::cerr << "Caught an unknown exception" << std::endl;
}
return 0;
}

View File

@ -0,0 +1,472 @@
/******************************************************************************
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
// STL includes
#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
// Xapian includes
#include <xapian.h>
#include "version.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/stat.h>
#endif
#define FIELD_TYPE 1
#define FIELD_NAME 2
#define FIELD_ARGS 3
#define FIELD_TAG 4
#define FIELD_URL 5
#define FIELD_KEYW 6
#define FIELD_DOC 7
#define HEX2DEC(x) (((x)>='0' && (x)<='9')?((x)-'0'):\
((x)>='a' && (x)<='f')?((x)-'a'+10):\
((x)>='A' && (x)<='F')?((x)-'A'+10):-1)
bool dirExists(const std::string& dirName)
{
#ifdef _WIN32
DWORD ftyp = GetFileAttributesA(dirName.c_str());
if (ftyp == INVALID_FILE_ATTRIBUTES)
return false; //something is wrong with your path!
if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
return true; // this is a directory!
#else
struct stat sb;
if (stat(dirName.c_str(), &sb)==0 && S_ISDIR(sb.st_mode))
{
return true;
}
#endif
return false;
}
/** decodes a URI encoded string into a normal string. */
static std::string uriDecode(const std::string & sSrc)
{
// Note from RFC1630: "Sequences which start with a percent
// sign but are not followed by two hexadecimal characters
// (0-9, A-F) are reserved for future extension"
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
const size_t SRC_LEN = sSrc.length();
const unsigned char * const SRC_END = pSrc + SRC_LEN;
// last decodable '%'
const unsigned char * const SRC_LAST_DEC = SRC_END - 2;
char * const pStart = new char[SRC_LEN];
char * pEnd = pStart;
while (pSrc < SRC_LAST_DEC)
{
if (*pSrc == '%') // replace %2A with corresponding ASCII character
{
char dec1, dec2;
unsigned char c1=*(pSrc+1);
unsigned char c2=*(pSrc+2);
if (-1 != (dec1 = HEX2DEC(c1))
&& -1 != (dec2 = HEX2DEC(c2)))
{
*pEnd++ = (dec1 << 4) + dec2;
pSrc += 3;
continue;
}
}
else if (*pSrc == '+') // replace '+' with space
{
*pEnd++ = ' '; pSrc++;
continue;
}
*pEnd++ = *pSrc++;
}
// the last 2- chars
while (pSrc < SRC_END) *pEnd++ = *pSrc++;
std::string sResult(pStart, pEnd);
delete [] pStart;
return sResult;
}
/** return list of strings that result when splitting \a s using
* delimiter \a delim
*/
static std::vector<std::string> split(const std::string &s, char delim)
{
std::vector<std::string> elems;
std::stringstream ss(s);
std::string item;
while (getline(ss, item, delim)) elems.push_back(item);
return elems;
}
/** Read type T from string \a s */
template<class T>
T fromString(const std::string& s)
{
std::istringstream stream (s);
T t;
stream >> t;
return t;
}
/** Class that holds the starting position of a word */
struct WordPosition
{
WordPosition(size_t s,size_t i) : start(s), index(i) {}
size_t start;
size_t index;
};
/** Class representing the '<' operator for WordPosition objects based on position. */
struct WordPosition_less
{
bool operator()(const WordPosition &p1,const WordPosition &p2)
{
return p1.start<p2.start;
}
};
/** Class that holds a text fragment */
struct Fragment
{
Fragment(const std::string &t,int occ) : text(t), occurrences(occ) {}
std::string text;
int occurrences;
};
/** Class representing the '>' operator for Fragment objects based on occurrence. */
struct Fragment_greater
{
bool operator()(const Fragment &p1,const Fragment &p2)
{
return p1.occurrences>p2.occurrences;
}
};
/** Class representing a range within a string */
struct Range
{
Range(size_t s,size_t e) : start(s), end(e) {}
size_t start;
size_t end;
};
/** Returns true if [start..start+len] is inside one of the \a ranges. */
static bool insideRange(const std::vector<Range> &ranges,size_t start,size_t len)
{
for (std::vector<Range>::const_iterator it = ranges.begin();
it!=ranges.end(); ++it
)
{
Range r = *it;
if (start>=r.start && start+len<r.end)
{
return true;
}
}
return false;
}
/** Returns a list of text \a fragments from \a s containing one or
* more \a words. The list is sorted according to the
* number of occurrences of words within the fragment.
*/
static void highlighter(const std::string &s,
const std::vector<std::string> &words,
std::vector<Fragment> &fragments)
{
const std::string spanStart="<span class=\"hl\">";
const std::string spanEnd="</span>";
const std::string dots="...";
const size_t fragLen = 60;
size_t sl=s.length();
// find positions of words in s
int j=0;
std::vector<WordPosition> positions;
for (std::vector<std::string>::const_iterator it=words.begin();
it!=words.end();
++it,++j
)
{
size_t pos=0;
size_t i;
std::string word = *it;
while ((i=s.find(word,pos))!=std::string::npos)
{
positions.push_back(WordPosition(i,j));
pos=i+word.length();
}
}
// sort on position
std::sort(positions.begin(),positions.end(),WordPosition_less());
// get fragments around words
std::vector<Range> ranges;
for (std::vector<WordPosition>::const_iterator it=positions.begin();
it!=positions.end();
++it)
{
WordPosition wp = *it;
std::string w = words[wp.index];
size_t i=wp.start;
size_t wl=w.length();
if (!insideRange(ranges,i,wl))
{
if (wl>fragLen)
{
fragments.push_back(Fragment(spanStart+w+spanEnd,1));
ranges.push_back(Range(i,i+wl));
}
else
{
std::string startFragment,endFragment;
size_t bi=i-(fragLen-wl)/2;
size_t ei=i+wl+(fragLen-wl)/2;
int occ=0;
if (bi<0) { ei-=bi; bi=0; } else startFragment=dots;
if (ei>sl) { ei=sl; } else endFragment=dots;
while (bi>0 && !isspace(s[bi])) bi--; // round to start of the word
while (ei<sl && !isspace(s[ei])) ei++; // round to end of the word
// highlight any word in s between indexes bi and ei
std::string fragment=startFragment;
size_t pos=bi;
for (std::vector<WordPosition>::const_iterator it2=positions.begin();
it2!=positions.end();
++it2)
{
WordPosition wp2 = *it2;
std::string w2 = words[wp2.index];
size_t wl2 = w2.length();
if (wp2.start>=bi && wp2.start+wl2<=ei) // word is inside the range!
{
fragment+=s.substr(pos,wp2.start-pos)+
spanStart+
s.substr(wp2.start,wl2)+
spanEnd;
pos=wp2.start+wl2;
occ++;
}
}
fragment+=s.substr(pos,ei-pos)+endFragment;
fragments.push_back(Fragment(fragment,occ));
ranges.push_back(Range(bi,ei));
}
}
}
std::sort(fragments.begin(),fragments.end(),Fragment_greater());
}
/** Escapes a string such that is can be included in a JSON structure */
static std::string escapeString(const std::string &s)
{
std::stringstream dst;
for (size_t i=0;i<s.length();i++)
{
char ch = s[i];
switch (ch)
{
case '\"': dst << "\\\""; break;
default: dst << ch; break;
}
}
return dst.str();
}
static void showError(const std::string &callback,const std::string &error)
{
std::cout << callback << "({\"error\":\"" << error << "\"})";
exit(0);
}
static void usage(const char *name, int exitVal = 1)
{
std::cerr << "Usage: " << name << "[query_string]" << std::endl;
std::cerr << " " << "alternatively the query string can be given by the environment variable QUERY_STRING" << std::endl;
exit(exitVal);
}
/** Main routine */
int main(int argc,char **argv)
{
// process inputs that were passed to us via QUERY_STRING
std::string callback;
try
{
std::string queryString;
if (argc == 1)
{
const char *queryEnv = getenv("QUERY_STRING");
if (queryEnv)
{
queryString = queryEnv;
}
else
{
usage(argv[0]);
}
}
else if (argc == 2)
{
if (std::string(argv[1])=="-h" || std::string(argv[1])=="--help")
{
usage(argv[0],0);
}
else if (std::string(argv[1])=="-v" || std::string(argv[1])=="--version")
{
std::cerr << argv[0] << " version: " << getFullVersion() << std::endl;
exit(0);
}
else
{
queryString = argv[1];
}
}
else
{
usage(argv[0]);
}
std::cout << "Content-Type:application/javascript;charset=utf-8\r\n\n";
// parse query string
std::vector<std::string> parts = split(queryString,'&');
std::string searchFor,callback;
int num=1,page=0;
for (std::vector<std::string>::const_iterator it=parts.begin();it!=parts.end();++it)
{
std::vector<std::string> kv = split(*it,'=');
if (kv.size()==2)
{
std::string val = uriDecode(kv[1]);
if (kv[0]=="q") searchFor = val;
else if (kv[0]=="n") num = fromString<int>(val);
else if (kv[0]=="p") page = fromString<int>(val);
else if (kv[0]=="cb") callback = val;
}
}
std::string indexDir = "doxysearch.db";
if (queryString=="test") // user test
{
bool dbOk = dirExists(indexDir);
if (dbOk)
{
std::cout << "Test successful.";
}
else
{
std::cout << "Test failed: cannot find search index " << indexDir;
}
exit(0);
}
// create query
Xapian::Database db(indexDir);
Xapian::Enquire enquire(db);
std::vector<std::string> words = split(searchFor,' ');
Xapian::QueryParser parser;
parser.set_database(db);
parser.set_default_op(Xapian::Query::OP_AND);
parser.set_stemming_strategy(Xapian::QueryParser::STEM_ALL);
Xapian::termcount max_expansion=100;
#if (XAPIAN_MAJOR_VERSION==1) && (XAPIAN_MINOR_VERSION==2)
parser.set_max_wildcard_expansion(max_expansion);
#else
parser.set_max_expansion(max_expansion,Xapian::Query::WILDCARD_LIMIT_MOST_FREQUENT);
#endif
Xapian::Query query=parser.parse_query(searchFor,
Xapian::QueryParser::FLAG_DEFAULT |
Xapian::QueryParser::FLAG_WILDCARD |
Xapian::QueryParser::FLAG_PHRASE |
Xapian::QueryParser::FLAG_PARTIAL
);
enquire.set_query(query);
// get results
Xapian::MSet matches = enquire.get_mset(page*num,num);
unsigned int hits = matches.get_matches_estimated();
unsigned int offset = page*num;
unsigned int pages = num>0 ? (hits+num-1)/num : 0;
if (offset>hits) offset=hits;
if (offset+num>hits) num=hits-offset;
// write results as JSONP
std::cout << callback.c_str() << "(";
std::cout << "{" << std::endl
<< " \"hits\":" << hits << "," << std::endl
<< " \"first\":" << offset << "," << std::endl
<< " \"count\":" << num << "," << std::endl
<< " \"page\":" << page << "," << std::endl
<< " \"pages\":" << pages << "," << std::endl
<< " \"query\": \"" << escapeString(searchFor) << "\"," << std::endl
<< " \"items\":[" << std::endl;
// foreach search result
unsigned int o = offset;
for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i,++o)
{
std::vector<Fragment> hl;
Xapian::Document doc = i.get_document();
highlighter(doc.get_value(FIELD_DOC),words,hl);
std::cout << " {\"type\": \"" << doc.get_value(FIELD_TYPE) << "\"," << std::endl
<< " \"name\": \"" << doc.get_value(FIELD_NAME) << escapeString(doc.get_value(FIELD_ARGS)) << "\"," << std::endl
<< " \"tag\": \"" << doc.get_value(FIELD_TAG) << "\"," << std::endl
<< " \"url\": \"" << doc.get_value(FIELD_URL) << "\"," << std::endl;
std::cout << " \"fragments\":[" << std::endl;
int c=0;
bool first=true;
for (std::vector<Fragment>::const_iterator it = hl.begin();it!=hl.end() && c<3;++it,++c)
{
if (!first) std::cout << "," << std::endl;
std::cout << " \"" << escapeString((*it).text) << "\"";
first=false;
}
if (!first) std::cout << std::endl;
std::cout << " ]" << std::endl;
std::cout << " }";
if (o<offset+num-1) std::cout << ",";
std::cout << std::endl;
}
std::cout << " ]" << std::endl << "})" << std::endl;
}
catch (const Xapian::Error &e) // Xapian exception
{
showError(callback,e.get_description());
}
catch (...) // Any other exception
{
showError(callback,"Unknown Exception!");
exit(1);
}
return 0;
}

View File

@ -0,0 +1,124 @@
# search for Qt5
if (NOT force_qt4)
find_package(Qt5Core QUIET CONFIG)
if (Qt5Core_FOUND)
message(STATUS "Using Qt5")
find_package(Qt5 COMPONENTS Widgets Gui Xml)
macro(qt_wrap_cpp)
qt5_wrap_cpp(${ARGN})
endmacro()
macro(qt_add_resources)
qt5_add_resources(${ARGN})
endmacro()
endif()
endif()
# fallback to Qt4
if (NOT Qt5Core_FOUND)
if (NOT force_qt4)
message(STATUS "Qt5 not found, searching for Qt4 instead...")
else()
message(STATUS "Using Qt4")
endif()
find_package(Qt4 REQUIRED COMPONENTS QtCore QtXml QtGui)
macro(qt_wrap_cpp)
qt4_wrap_cpp(${ARGN})
endmacro()
macro(qt_add_resources)
qt4_add_resources(${ARGN})
endmacro()
endif()
include_directories(
.
${PROJECT_SOURCE_DIR}/libversion
${PROJECT_SOURCE_DIR}/qtools
${GENERATED_SRC}
)
set(GENERATED_SRC_WIZARD ${GENERATED_SRC}/doxywizard)
file(MAKE_DIRECTORY ${GENERATED_SRC_WIZARD})
add_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII -DUNICODE)
if (NOT Qt5Core_FOUND)
include(${QT_USE_FILE})
endif()
# generate settings.h
file(GENERATE OUTPUT ${GENERATED_SRC_WIZARD}/settings.h
CONTENT "#ifndef SETTINGS_H
#define SETTINGS_H
#define USE_SQLITE3 ${sqlite3}
#define USE_LIBCLANG ${clang}
#define IS_SUPPORTED(x) \\
((USE_SQLITE3 && strcmp(\"USE_SQLITE3\",(x))==0) || \\
(USE_LIBCLANG && strcmp(\"USE_LIBCLANG\",(x))==0) || \\
0)
#endif" )
set_source_files_properties(${GENERATED_SRC_WIZARD}/settings.h PROPERTIES GENERATED 1)
# generate version.cpp
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/version.py ${VERSION} > ${GENERATED_SRC_WIZARD}/version.cpp
DEPENDS ${PROJECT_SOURCE_DIR}/VERSION ${PROJECT_SOURCE_DIR}/src/version.py
OUTPUT ${GENERATED_SRC_WIZARD}/version.cpp
)
set_source_files_properties(${GENERATED_SRC_WIZARD}/version.cpp PROPERTIES GENERATED 1)
# generate configdoc.cpp
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/configgen.py -wiz ${PROJECT_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC_WIZARD}/configdoc.cpp
DEPENDS ${PROJECT_SOURCE_DIR}/src/configgen.py ${PROJECT_SOURCE_DIR}/src/config.xml
OUTPUT ${GENERATED_SRC_WIZARD}/configdoc.cpp
)
set_source_files_properties(${GENERATED_SRC_WIZARD}/configdoc.cpp PROPERTIES GENERATED 1)
set(LEX_FILES config_doxyw)
foreach(lex_file ${LEX_FILES})
add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/addon/doxywizard/${lex_file}.l > ${GENERATED_SRC_WIZARD}/${lex_file}.l.h
DEPENDS ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/addon/doxywizard/${lex_file}.l
OUTPUT ${GENERATED_SRC_WIZARD}/${lex_file}.l.h
)
set_source_files_properties(${GENERATED_SRC_WIZARD}/${lex_file}.l.h PROPERTIES GENERATED 1)
FLEX_TARGET(${lex_file} ${lex_file}.l ${GENERATED_SRC_WIZARD}/${lex_file}.cpp COMPILE_FLAGS "${LEX_FLAGS}")
endforeach()
qt_wrap_cpp(doxywizard_MOC
doxywizard.h
expert.h
helplabel.h
inputint.h
inputbool.h
inputstring.h
inputstrlist.h
wizard.h
)
qt_add_resources(doxywizard_RESOURCES_RCC doxywizard.qrc)
add_executable(doxywizard WIN32
config_msg.cpp
doxywizard.cpp
expert.cpp
wizard.cpp
inputbool.cpp
inputstring.cpp
inputint.cpp
inputstrlist.cpp
${GENERATED_SRC_WIZARD}/settings.h
${GENERATED_SRC_WIZARD}/config_doxyw.cpp
${GENERATED_SRC_WIZARD}/config_doxyw.l.h
${GENERATED_SRC_WIZARD}/configdoc.cpp
${doxywizard_MOC}
${doxywizard_RESOURCES_RCC}
doxywizard.rc
)
if(Qt5Core_FOUND)
target_link_libraries(doxywizard Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Xml doxygen_version)
else()
target_link_libraries(doxywizard ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} doxygen_version)
endif()
install(TARGETS doxywizard DESTINATION bin)

3
addon/doxywizard/README Normal file
View File

@ -0,0 +1,3 @@
Doxywizard is a graphical front-end to read/edit/write doxygen configuration
files and to launch doxygen. It requires Qt version 4.3 or higher.

39
addon/doxywizard/config.h Normal file
View File

@ -0,0 +1,39 @@
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef CONFIG_H
#define CONFIG_H
#include <QHash>
#include <QString>
class Input;
class QTextStream;
class QTextCodec;
bool parseConfig(
const QString &fileName,
const QHash<QString,Input *> &options
);
void writeStringValue(QTextStream &t,QTextCodec *codec,const QString &s);
// directly copied from ../../src/config.h to be consistent
enum
{
/*! Maximum length of an option in the config file. Used for
* alignment purposes.
*/
MAX_OPTION_LENGTH = 23
};
#endif

View File

@ -0,0 +1,768 @@
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
%option never-interactive
%option prefix="config_doxywYY"
%top{
#include <stdint.h>
}
%{
/*
* includes
*/
#include "config.h"
#include "input.h"
#include "inputstring.h"
#include "config_msg.h"
#include <QString>
#include <QVariant>
#include <QStack>
#include <QTextCodec>
#include <QByteArray>
#include <QFileInfo>
#include <QStringList>
#include <QRegExp>
#include <QTextStream>
#include <QMessageBox>
#define YY_NO_UNISTD_H 1
#define MAX_INCLUDE_DEPTH 10
/* -----------------------------------------------------------------
*
* static variables
*/
struct ConfigFileState
{
int lineNr;
FILE *file;
YY_BUFFER_STATE oldState;
YY_BUFFER_STATE newState;
QString fileName;
};
static const QHash<QString,Input*> *g_options;
static FILE *g_file;
static QString g_yyFileName;
static QString g_includeName;
static QVariant g_includePathList;
static QStack<ConfigFileState*> g_includeStack;
static int g_includeDepth;
static QVariant *g_arg;
static Input *g_curOption=0;
static QByteArray g_str;
static QTextCodec *g_codec = QTextCodec::codecForName("UTF-8");
static QString g_codecName = QString::fromLatin1("UTF-8");
static QString g_cmd;
static bool g_isEnum;
static const char *stateToString(int state);
/* -----------------------------------------------------------------
*/
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
static yy_size_t yyread(char *buf,yy_size_t maxSize)
{
// no file included
if (g_includeStack.isEmpty())
{
return fread(buf,1,maxSize,g_file);
}
else
{
return fread(buf,1,maxSize,g_includeStack.top()->file);
}
}
static void substEnvVarsInStrList(QStringList &sl);
static void substEnvVarsInString(QString &s);
static void checkEncoding()
{
Input *option = g_options->value(QString::fromLatin1("DOXYFILE_ENCODING"));
if (option && option->value().toString()!=g_codecName)
{
QTextCodec *newCodec = QTextCodec::codecForName(option->value().toString().toLatin1());
if (newCodec)
{
g_codec = newCodec;
g_codecName = option->value().toString();
}
}
}
static QByteArray stripComment(const QByteArray &s)
{
// check if there is a comment at the end of the string
bool insideQuote=false;
int l = s.length();
for (int i=0;i<l;i++)
{
char c = s.at(i);
if (c=='\\') // skip over escaped characters
{
i++;
}
else if (c=='"') // toggle inside/outside quotation
{
insideQuote=!insideQuote;
}
else if (!insideQuote && c=='#') // found start of a comment
{
return s.left(i).trimmed();
}
}
return s;
}
static void processString()
{
// strip leading and trailing whitespace
QByteArray s = stripComment(g_str.trimmed());
int l = s.length();
// remove surrounding quotes if present (and not escaped)
if (l>=2 && s.at(0)=='"' && s.at(l-1)=='"' && // remove quotes
(s.at(l-2)!='\\' || (s.at(l-2)=='\\' && s.at(l-3)=='\\')))
{
s=s.mid(1,s.length()-2);
l=s.length();
}
// check for invalid and/or escaped quotes
bool warned=false;
QByteArray result;
for (int i=0;i<l;i++)
{
char c = s.at(i);
if (c=='\\') // escaped character
{
if (i<l-1 && s.at(i+1)=='"') // unescape the quote character
{
result+='"';
}
else // keep other escaped characters in escaped form
{
result+=c;
if (i<l-1)
{
result+=s.at(i+1);
}
}
i++; // skip over the escaped character
}
else if (c=='"') // unescaped quote
{
if (!warned)
{
std::string str = g_str.trimmed().data();
config_warn("Invalid value for '%s' tag at line %d, file %s: Value '%s' is not properly quoted\n",
qPrintable(g_cmd),yylineno-1,qPrintable(g_yyFileName),str.c_str());
}
warned=true;
}
else // normal character
{
result+=c;
}
}
// recode the string
if (g_isEnum)
{
InputString *cur = dynamic_cast<InputString *>(g_curOption);
*g_arg = cur->checkEnumVal(g_codec->toUnicode(result));
}
else
{
*g_arg = QVariant(g_codec->toUnicode(result));
}
// update encoding
checkEncoding();
//printf("Processed string '%s'\n",g_string->data());
}
static void processList()
{
bool allowCommaAsSeparator = g_cmd!=QString::fromLatin1("PREDEFINED");
const QByteArray s = stripComment(g_str.trimmed());
int l = s.length();
QByteArray elemStr;
// helper to push elemStr to the list and clear it
auto addElem = [&elemStr]()
{
if (!elemStr.isEmpty())
{
//printf("Processed list element '%s'\n",e.data());
*g_arg = QVariant(g_arg->toStringList() << g_codec->toUnicode(elemStr));
elemStr="";
}
};
bool needsSeparator=false;
int insideQuote=false;
bool warned=false;
for (int i=0;i<l;i++)
{
char c = s.at(i);
if (!needsSeparator && c=='\\') // escaped character
{
if (i<l-1 && s.at(i+1)=='"') // unescape the quote character
{
elemStr+='"';
}
else // keep other escaped characters in escaped form
{
elemStr+=c;
if (i<l-1)
{
elemStr+=s.at(i+1);
}
}
i++; // skip over the escaped character
}
else if (!needsSeparator && c=='"') // quote character
{
if (!insideQuote)
{
insideQuote=true;
}
else // this quote ends an element
{
insideQuote=false;
needsSeparator=true;
}
}
else if (!insideQuote && ((c==',' && allowCommaAsSeparator) || isspace(c))) // separator
{
needsSeparator=false;
addElem();
}
else // normal content character
{
if (needsSeparator)
{
if (!warned)
{
std::string str = g_str.trimmed().data();
config_warn("Invalid value for '%s' tag at line %d, file %s: Values in list '%s' are not properly space %sseparated\n",
qPrintable(g_cmd),yylineno-1,qPrintable(g_yyFileName),str.c_str(),allowCommaAsSeparator?"or comma ":"");
warned=true;
}
needsSeparator=false;
i--; // try the character again as part of a new element
addElem();
}
else
{
elemStr+=c;
}
}
}
// add last part
addElem();
if (insideQuote)
{
std::string str = g_str.trimmed().data();
config_warn("Invalid value for '%s' tag at line %d, file %s: Values in list '%s' are not properly quoted\n",
qPrintable(g_cmd),yylineno-1,qPrintable(g_yyFileName),str.c_str());
}
}
static FILE *tryPath(const QString &path,const QString &fileName)
{
QString absName=!path.isEmpty() ? path+QString::fromLatin1("/")+fileName : fileName;
QFileInfo fi(absName);
if (fi.exists() && fi.isFile())
{
FILE *f = fopen(absName.toLocal8Bit(),"r");
if (f==NULL)
config_err("could not open file %s for reading\n",qPrintable(absName));
else
return f;
}
return NULL;
}
static FILE *findFile(const QString &fileName)
{
if (QFileInfo(fileName).isAbsolute()) // absolute path
{
return tryPath(QString(), fileName);
}
// relative path, try with include paths in the list
QStringList sl = g_includePathList.toStringList();
substEnvVarsInStrList(sl);
foreach (QString s, sl)
{
FILE *f = tryPath(s,fileName);
if (f) return f;
}
// try cwd if g_includePathList fails
return tryPath(QString::fromLatin1("."),fileName);
}
static void readIncludeFile(const QString &incName)
{
if (g_includeDepth==MAX_INCLUDE_DEPTH)
{
config_err("maximum include depth (%d) reached, %s is not included.",
MAX_INCLUDE_DEPTH,qPrintable(incName));
}
QString inc = incName;
substEnvVarsInString(inc);
inc = inc.trimmed();
uint incLen = inc.length();
if (inc.at(0)==QChar::fromLatin1('"') &&
inc.at(incLen-1)==QChar::fromLatin1('"')) // strip quotes
{
inc=inc.mid(1,incLen-2);
}
FILE *f = findFile(inc);
if (f) // see if the include file can be found
{
// For debugging
#if SHOW_INCLUDES
for (i=0;i<includeStack.count();i++) msg(" ");
msg("@INCLUDE = %s: parsing...\n",qPrintable(inc));
#endif
// store the state of the old file
ConfigFileState *fs=new ConfigFileState;
fs->oldState=YY_CURRENT_BUFFER;
fs->fileName=g_yyFileName;
fs->file=f;
// push the state on the stack
g_includeStack.push(fs);
// set the scanner to the include file
yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
fs->newState=YY_CURRENT_BUFFER;
g_yyFileName=inc;
g_includeDepth++;
}
else
{
config_err("@INCLUDE = %s: not found!\n",qPrintable(inc));
}
}
%}
%option nounput
%option noyywrap
%option yylineno
%x Start
%x SkipInvalid
%x GetString
%x GetEnum
%x GetStrList
%x GetQuotedString
%x Include
%%
<*>\0x0d
/*-------------- Comments ---------------*/
<Start>"#".*\n { /* Skip comment */ }
/*-------------- TAG start ---------------*/
<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { g_cmd = g_codec->toUnicode(yytext);
g_cmd=g_cmd.left(g_cmd.length()-1).trimmed();
g_curOption = g_options->value(g_cmd);
if (g_curOption==0) // oops not known
{
config_warn("ignoring unsupported tag '%s' at line %d, file %s\n",
qPrintable(g_cmd),yylineno,qPrintable(g_yyFileName));
BEGIN(SkipInvalid);
}
else // known tag
{
g_arg = &g_curOption->value();
g_str = QByteArray();
g_isEnum = false;
switch(g_curOption->kind())
{
case Input::StrList:
*g_arg = QStringList();
BEGIN(GetStrList);
break;
case Input::String:
g_isEnum = dynamic_cast<InputString *>(g_curOption)->stringMode() == InputString::StringFixed;
BEGIN(GetString);
break;
case Input::Int:
BEGIN(GetString);
break;
case Input::Bool:
BEGIN(GetString);
break;
case Input::Obsolete:
config_warn("Tag '%s' at line %d of file %s has become obsolete.\n"
"To avoid this warning please update your configuration "
"file using \"doxygen -u\"\n", qPrintable(g_cmd),
yylineno,qPrintable(g_yyFileName));
BEGIN(SkipInvalid);
break;
}
}
}
<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { g_cmd=g_codec->toUnicode(yytext);
g_cmd=g_cmd.left(g_cmd.length()-2).trimmed();
g_curOption = g_options->value(g_cmd);
if (g_curOption==0) // oops not known
{
config_warn("ignoring unsupported tag '%s' at line %d, file %s\n",
yytext,yylineno,qPrintable(g_yyFileName));
BEGIN(SkipInvalid);
}
else // known tag
{
switch(g_curOption->kind())
{
case Input::StrList:
g_arg = &g_curOption->value();
g_str=QByteArray();
BEGIN(GetStrList);
break;
case Input::String:
case Input::Int:
case Input::Bool:
config_warn("operator += not supported for '%s'. Ignoring line %d, file %s\n",
qPrintable(g_cmd),yylineno,qPrintable(g_yyFileName));
BEGIN(SkipInvalid);
break;
case Input::Obsolete:
config_warn("Tag '%s' at line %d of file %s has become obsolete.\n"
"To avoid this warning please update your configuration "
"file using \"doxygen -u\"\n",
qPrintable(g_cmd),yylineno,qPrintable(g_yyFileName));
BEGIN(SkipInvalid);
break;
}
}
}
/*-------------- INCLUDE* ---------------*/
<Start>"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); g_arg=&g_includePathList; *g_arg = QStringList(); g_str=QByteArray(); }
/* include a config file */
<Start>"@INCLUDE"[ \t]*"=" { BEGIN(Include);}
<Include>([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") {
readIncludeFile(g_codec->toUnicode(yytext));
BEGIN(Start);
}
<<EOF>> {
//printf("End of include file\n");
//printf("Include stack depth=%d\n",g_includeStack.count());
if (g_includeStack.isEmpty())
{
//printf("Terminating scanner!\n");
yyterminate();
}
else
{
ConfigFileState *fs = g_includeStack.pop();
fclose(fs->file);
YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
yy_switch_to_buffer( fs->oldState );
yy_delete_buffer( oldBuf );
g_yyFileName=fs->fileName;
delete fs;
g_includeDepth--;
}
}
<Start>[a-z_A-Z0-9]+ { config_warn("ignoring unknown tag '%s' at line %d, file %s\n",yytext,yylineno,qPrintable(g_yyFileName)); }
/*-------------- GetString ---------------*/
<GetString>\n { // end of string
processString();
BEGIN(Start);
}
<GetString>\\[ \r\t]*\n { // line continuation
g_str+=' ';
}
<GetString>"\\" { // escape character
g_str+=yytext;
}
<GetString>[^\n\\]+ { // string part without escape characters
g_str+=yytext;
}
/*-------------- GetStrList ---------------*/
<GetStrList>\n { // end of list
processList();
BEGIN(Start);
}
<GetStrList>\\[ \r\t]*\n { // line continuation
g_str+=' ';
}
<GetStrList>"\\" { // escape character
g_str+=yytext;
}
<GetStrList>[^\n\\]+ { // string part without escape characters
g_str+=yytext;
}
/*-------------- SkipInvalid ---------------*/
<SkipInvalid>\n { // end of skipped part
BEGIN(Start);
}
<SkipInvalid>\\[ \r\t]*\n { // line continuation
g_str+=' ';
}
<SkipInvalid>"\\" { // escape character
g_str+=yytext;
}
<SkipInvalid>[^\n\\]+ { // string part without escape characters
g_str+=yytext;
}
/*-------------- fall through -------------*/
<*>\\[ \r\t]*\n { }
<*>[ \r\t] { }
<*>\n
<*>. { config_warn("ignoring unknown character '%c' at line %d, file %s\n",yytext[0],yylineno,qPrintable(g_yyFileName)); }
%%
/*@ ----------------------------------------------------------------------------
*/
static void substEnvVarsInString(QString &s)
{
static QRegExp re(QString::fromLatin1("\\$\\([a-z_A-Z0-9]+\\)"));
if (s.isEmpty()) return;
int p=0;
int i,l;
//printf("substEnvVarInString(%s) start\n",qPrintable(s));
while ((i=re.indexIn(s,p))!=-1)
{
l = re.matchedLength();
//printf("Found environment var s.mid(%d,%d)='%s'\n",i+2,l-3,qPrintable(s.mid(i+2,l-3)));
QString env=g_codec->toUnicode(getenv(s.mid(i+2,l-3).toLatin1()));
substEnvVarsInString(env); // recursively expand variables if needed.
s = s.left(i)+env+s.right(s.length()-i-l);
p=i+env.length(); // next time start at the end of the expanded string
}
s=s.trimmed(); // to strip the bogus space that was added when an argument
// has quotes
//printf("substEnvVarInString(%s) end\n",qPrintable(s));
}
static void substEnvVarsInStrList(QStringList &sl)
{
QStringList out;
foreach (QString result, sl)
{
// an argument with quotes will have an extra space at the end, so wasQuoted will be TRUE.
bool wasQuoted = (result.indexOf(QChar::fromLatin1(' '))!=-1) ||
(result.indexOf(QChar::fromLatin1('\t'))!=-1);
// here we strip the quote again
substEnvVarsInString(result);
//printf("Result %s was quoted=%d\n",qPrintable(result),wasQuoted);
if (!wasQuoted) /* as a result of the expansion, a single string
may have expanded into a list, which we'll
add to sl. If the original string already
contained multiple elements no further
splitting is done to allow quoted items with spaces! */
{
int l=result.length();
int i,p=0;
// skip spaces
// search for a "word"
for (i=0;i<l;i++)
{
QChar c=0;
// skip until start of new word
while (i<l && ((c=result.at(i))==QChar::fromLatin1(' ') || c==QChar::fromLatin1('\t'))) i++;
p=i; // p marks the start index of the word
// skip until end of a word
while (i<l && ((c=result.at(i))!=QChar::fromLatin1(' ') &&
c!=QChar::fromLatin1('\t') &&
c!=QChar::fromLatin1('"'))) i++;
if (i<l) // not at the end of the string
{
if (c==QChar::fromLatin1('"')) // word within quotes
{
p=i+1;
for (i++;i<l;i++)
{
c=result.at(i);
if (c==QChar::fromLatin1('"')) // end quote
{
out += result.mid(p,i-p);
p=i+1;
break;
}
else if (c==QChar::fromLatin1('\\')) // skip escaped stuff
{
i++;
}
}
}
else if (c==QChar::fromLatin1(' ') || c==QChar::fromLatin1('\t')) // separator
{
out += result.mid(p,i-p);
p=i+1;
}
}
}
if (p!=l) // add the leftover as a string
{
out += result.right(l-p);
}
}
else // just goto the next element in the list
{
out += result;
}
}
sl = out;
}
//--------------------------------------------------------------------------
bool parseConfig(
const QString &fileName,
const QHash<QString,Input *> &options
)
{
yylineno = 1;
config_open();
QHashIterator<QString, Input*> i(options);
g_file = fopen(fileName.toLocal8Bit(),"r");
if (g_file==NULL) return false;
// reset all values
i.toFront();
while (i.hasNext())
{
i.next();
if (i.value())
{
i.value()->reset();
}
}
// parse config file
g_options = &options;
g_yyFileName = fileName;
g_includeStack.clear();
g_includeDepth = 0;
config_doxywYYrestart( config_doxywYYin );
BEGIN( Start );
config_doxywYYlex();
// update the values in the UI
i.toFront();
while (i.hasNext())
{
i.next();
if (i.value())
{
//printf("Updating: %s\n",qPrintable(i.key()));
i.value()->update();
}
else
{
printf("Invalid option: %s\n",qPrintable(i.key()));
}
}
fclose(g_file);
config_finish();
return true;
}
void writeStringValue(QTextStream &t,QTextCodec *codec,const QString &s)
{
QChar c;
bool needsEscaping=false;
bool needsHashEscaping=false;
// convert the string back to it original encoding
//QByteArray se = codec->fromUnicode(s);
t.setCodec(codec);
const QChar *p=s.data();
if (!s.isEmpty() && !p->isNull())
{
if (*p != QChar::fromLatin1('"'))
{
while (!(c=*p++).isNull() && !needsEscaping)
{
needsEscaping = (c==QChar::fromLatin1(' ') ||
c==QChar::fromLatin1(',') ||
c==QChar::fromLatin1('\n') ||
c==QChar::fromLatin1('\t') ||
c==QChar::fromLatin1('"'));
}
p=s.data();
while (!(c=*p++).isNull() && !needsHashEscaping)
{
needsHashEscaping = (c==QChar::fromLatin1('#'));
}
}
if (needsHashEscaping || needsEscaping)
{
t << "\"";
}
if (needsEscaping)
{
p=s.data();
while (!p->isNull())
{
if (*p ==QChar::fromLatin1(' ') &&
*(p+1)==QChar::fromLatin1('\0')) break; // skip inserted space at the end
if (*p ==QChar::fromLatin1('"')) t << "\\"; // escape quotes
t << *p++;
}
}
else
{
t << s;
}
if (needsHashEscaping || needsEscaping)
{
t << "\"";
}
}
}
#include "config_doxyw.l.h"

View File

@ -0,0 +1,56 @@
#include <QString>
#include "config_msg.h"
#include "doxywizard.h"
static QString warning_str = QString::fromLatin1("warning: ");
static QString error_str = QString::fromLatin1("error: ");
void config_err(const char *fmt, ...)
{
QString msg = error_str;
msg.append(QString::fromLatin1(fmt));
va_list args;
va_start(args, fmt);
char debugOut[1000]; // this size should be sufficient
vsnprintf(debugOut, 1000,qPrintable(msg), args);
MainWindow::instance().outputLogText(QString::fromLatin1(debugOut));
va_end(args);
}
void config_term(const char *fmt, ...)
{
QString msg = error_str;
msg.append(QString::fromLatin1(fmt));
va_list args;
va_start(args, fmt);
char debugOut[1000]; // this size should be sufficient
vsnprintf(debugOut, 1000,qPrintable(msg), args);
MainWindow::instance().outputLogText(QString::fromLatin1(debugOut));
va_end(args);
exit(1);
}
void config_warn(const char *fmt, ...)
{
QString msg = warning_str;
msg.append(QString::fromLatin1(fmt));
va_list args;
va_start(args, fmt);
char debugOut[1000];
vsnprintf(debugOut, 1000,qPrintable(msg), args);
MainWindow::instance().outputLogText(QString::fromLatin1(debugOut));
va_end(args);
}
void config_open()
{
MainWindow::instance().outputLogStart();
}
void config_finish()
{
MainWindow::instance().outputLogFinish();
}

View File

@ -0,0 +1,10 @@
#ifndef DOXYW_MSG_H
#define DOXYW_MSG_H
void config_err(const char *fmt, ...);
void config_term(const char *fmt, ...);
void config_warn(const char *fmt, ...);
void config_open();
void config_finish();
#endif

View File

@ -0,0 +1,20 @@
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef CONFIGDOC_H
#define CONFIGDOC_H
class DocIntf;
void addConfigDocs(DocIntf *doc);
#endif

View File

@ -0,0 +1,24 @@
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef DOCINTF_H
#define DOCINTF_H
class DocIntf
{
public:
virtual ~DocIntf() {}
virtual void setHeader(const char *header) = 0;
virtual void add(const char *name,const char *docs) = 0;
};
#endif

827
addon/doxywizard/doxywizard.cpp Executable file
View File

@ -0,0 +1,827 @@
/******************************************************************************
*
* Copyright (C) 1997-2021 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include "doxywizard.h"
#include "version.h"
#include "expert.h"
#include "wizard.h"
#include <QMenu>
#include <QMenuBar>
#include <QPushButton>
#include <QMessageBox>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QLabel>
#include <QCheckBox>
#include <QTextBrowser>
#include <QStatusBar>
#include <QProcess>
#include <QTimer>
#include <QCloseEvent>
#include <QApplication>
#include <QDir>
#include <QFileDialog>
#include <QDesktopServices>
#include <QUrl>
#include <QTextStream>
#include <QDebug>
#ifdef WIN32
#include <windows.h>
#endif
#define MAX_RECENT_FILES 10
// globally accessible variables
bool DoxygenWizard::debugFlag = false;
const int messageTimeout = 5000; //!< status bar message timeout in milliseconds.
#define APPQT(x) QString::fromLatin1("<qt><pre>") + x + QString::fromLatin1("</pre></qt>")
static QString text1 = QString::fromLatin1("");
MainWindow &MainWindow::instance()
{
static MainWindow *theInstance = new MainWindow;
return *theInstance;
}
MainWindow::MainWindow()
: m_settings(QString::fromLatin1("Doxygen.org"), QString::fromLatin1("Doxywizard"))
{
QMenu *file = menuBar()->addMenu(tr("File"));
file->addAction(tr("Open..."),
this, SLOT(openConfig()), Qt::CTRL+Qt::Key_O);
m_recentMenu = file->addMenu(tr("Open recent"));
file->addAction(tr("Save"),
this, SLOT(saveConfig()), Qt::CTRL+Qt::Key_S);
file->addAction(tr("Save as..."),
this, SLOT(saveConfigAs()), Qt::SHIFT+Qt::CTRL+Qt::Key_S);
file->addAction(tr("Quit"),
this, SLOT(quit()), Qt::CTRL+Qt::Key_Q);
QMenu *settings = menuBar()->addMenu(tr("Settings"));
m_resetDefault = settings->addAction(tr("Reset to factory defaults"),
this,SLOT(resetToDefaults()));
settings->addAction(tr("Use current settings at startup"),
this,SLOT(makeDefaults()));
m_clearRecent = settings->addAction(tr("Clear recent list"),
this,SLOT(clearRecent()));
QMenu *help = menuBar()->addMenu(tr("Help"));
help->addAction(tr("Online manual"),
this, SLOT(manual()), Qt::Key_F1);
help->addAction(tr("About"),
this, SLOT(about()) );
m_expert = new Expert;
m_wizard = new Wizard(m_expert->modelData());
// ----------- top part ------------------
QWidget *mainPart = new QWidget;
QVBoxLayout *mainLayout = new QVBoxLayout(mainPart);
QWidget *topPart = new QWidget;
QVBoxLayout *rowLayout = new QVBoxLayout(topPart);
mainLayout->addWidget(topPart);
// select working directory
QHBoxLayout *dirLayout = new QHBoxLayout;
m_workingDir = new QLineEdit;
m_selWorkingDir = new QPushButton(tr("Select..."));
dirLayout->addWidget(m_workingDir);
dirLayout->addWidget(m_selWorkingDir);
//------------- bottom part --------------
QWidget *runTab = new QWidget;
QVBoxLayout *runTabLayout = new QVBoxLayout(runTab);
// run doxygen
QHBoxLayout *runLayout = new QHBoxLayout;
m_run = new QPushButton(tr("Run doxygen"));
m_run->setEnabled(false);
m_runStatus = new QLabel(tr("Status: not running"));
m_saveLog = new QPushButton(tr("Save log..."));
m_saveLog->setEnabled(false);
QPushButton *showSettings = new QPushButton(tr("Show configuration"));
m_showCondensedSettings = new QCheckBox(this);
m_showCondensedSettings->setText(tr("Condensed"));
m_showCondensedSettings->setChecked(false);
m_showCondensedSettings->setToolTip(tr("Show only configuration settings different from default settings"));
// select extra run options
m_runOptions = new QLineEdit;
runTabLayout->addWidget(new QLabel(tr("Specify additional command line options for running doxygen")));
runTabLayout->addWidget(m_runOptions);
QVBoxLayout *runVLayout = new QVBoxLayout;
runLayout->addLayout(runVLayout);
QHBoxLayout *runVHLayout = new QHBoxLayout;
runVLayout->addLayout(runVHLayout);
runVHLayout->addWidget(m_run);
runVHLayout->addWidget(m_runStatus);
QHBoxLayout *runVH2Layout = new QHBoxLayout;
runVLayout->addLayout(runVH2Layout);
m_launchHtml = new QPushButton(tr("Show HTML output"));
runVH2Layout->addWidget(m_launchHtml);
runVH2Layout->addStretch(1); // to have launch button not being stretched
runLayout->addStretch(1);
QVBoxLayout *settingsLayout = new QVBoxLayout;
runLayout->addLayout(settingsLayout);
settingsLayout->addWidget(m_showCondensedSettings);
settingsLayout->addWidget(showSettings);
QVBoxLayout *saveLayout = new QVBoxLayout;
runLayout->addLayout(saveLayout);
saveLayout->addWidget(m_saveLog);
saveLayout->setAlignment(Qt::AlignTop);
// saveLayout->addWidget(new QWidget); // to have the save button at the top
// output produced by Doxygen
runTabLayout->addLayout(runLayout);
runTabLayout->addWidget(new QLabel(tr("Output produced by doxygen")));
QGridLayout *grid = new QGridLayout;
//m_outputLog = new QTextEdit;
m_outputLog = new QTextBrowser;
//m_outputLog = new QPlainTextEdit;
m_outputLog->setReadOnly(true);
m_outputLog->setFontFamily(QString::fromLatin1("courier"));
m_outputLog->setMinimumWidth(600);
grid->addWidget(m_outputLog,0,0);
grid->setColumnStretch(0,1);
grid->setRowStretch(0,1);
runTabLayout->addLayout(grid);
m_tabs = new QTabWidget;
m_tabs->addTab(m_wizard,tr("Wizard"));
m_tabs->addTab(m_expert,tr("Expert"));
m_tabs->addTab(runTab,tr("Run"));
rowLayout->addWidget(new QLabel(tr("Specify the working directory from which doxygen will run")));
rowLayout->addLayout(dirLayout);
rowLayout->addWidget(new QLabel(tr("Configure doxygen using the Wizard and/or Expert tab, then switch to the Run tab to generate the documentation")));
mainLayout->addWidget(m_tabs);
setCentralWidget(mainPart);
statusBar()->showMessage(tr("Welcome to Doxygen"),messageTimeout);
m_runProcess = new QProcess;
m_running = false;
m_timer = new QTimer;
// connect signals and slots
connect(m_tabs,SIGNAL(currentChanged(int)),SLOT(selectTab(int)));
connect(m_selWorkingDir,SIGNAL(clicked()),SLOT(selectWorkingDir()));
connect(m_recentMenu,SIGNAL(triggered(QAction*)),SLOT(openRecent(QAction*)));
connect(m_workingDir,SIGNAL(returnPressed()),SLOT(updateWorkingDir()));
connect(m_runProcess,SIGNAL(readyReadStandardOutput()),SLOT(readStdout()));
connect(m_runProcess,SIGNAL(finished(int, QProcess::ExitStatus)),SLOT(runComplete()));
connect(m_timer,SIGNAL(timeout()),SLOT(readStdout()));
connect(m_run,SIGNAL(clicked()),SLOT(runDoxygen()));
connect(m_launchHtml,SIGNAL(clicked()),SLOT(showHtmlOutput()));
connect(m_saveLog,SIGNAL(clicked()),SLOT(saveLog()));
connect(showSettings,SIGNAL(clicked()),SLOT(showSettings()));
connect(m_expert,SIGNAL(changed()),SLOT(configChanged()));
connect(m_wizard,SIGNAL(done()),SLOT(selectRunTab()));
connect(m_expert,SIGNAL(done()),SLOT(selectRunTab()));
loadSettings();
updateLaunchButtonState();
m_modified = false;
updateTitle();
m_wizard->refresh();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if (discardUnsavedChanges())
{
saveSettings();
event->accept();
}
else
{
event->ignore();
}
}
void MainWindow::quit()
{
if (discardUnsavedChanges())
{
saveSettings();
}
else
{
return;
}
QApplication::exit(0);
}
void MainWindow::setWorkingDir(const QString &dirName)
{
QDir::setCurrent(dirName);
m_workingDir->setText(dirName);
m_run->setEnabled(!dirName.isEmpty());
}
void MainWindow::selectWorkingDir()
{
QString dirName = QFileDialog::getExistingDirectory(this,
tr("Select working directory"),m_workingDir->text());
if (!dirName.isEmpty())
{
setWorkingDir(dirName);
}
}
void MainWindow::updateWorkingDir()
{
setWorkingDir(m_workingDir->text());
}
void MainWindow::manual()
{
QDesktopServices::openUrl(QUrl(QString::fromLatin1("https://www.doxygen.org/manual/index.html")));
}
void MainWindow::about()
{
QString msg;
QTextStream t(&msg,QIODevice::WriteOnly);
t << QString::fromLatin1("<qt><center>A tool to configure and run doxygen version ")+
QString::fromLatin1(getDoxygenVersion())+
QString::fromLatin1(" on your source files.</center>")+
QString::fromLatin1("<center>(Created with Qt version ")+
QString::fromLatin1(QT_VERSION_STR);
if (qstrcmp(qVersion(),QT_VERSION_STR))
{
t << QString::fromLatin1(", running with ")+
QString::fromLatin1(qVersion());
}
t << QString::fromLatin1(")</center><p><br>"
"<center>Written by<br> Dimitri van Heesch<br>&copy; 2000-2021</center><p>"
"</qt>");
QMessageBox::about(this,tr("Doxygen GUI"),msg);
}
void MainWindow::openConfig()
{
if (discardUnsavedChanges(false))
{
QString fn = QFileDialog::getOpenFileName(this,
tr("Open configuration file"),
m_workingDir->text());
if (!fn.isEmpty())
{
loadConfigFromFile(fn);
}
}
}
void MainWindow::updateConfigFileName(const QString &fileName)
{
if (m_fileName!=fileName)
{
m_fileName = fileName;
QString curPath = QFileInfo(fileName).path();
setWorkingDir(curPath);
addRecentFile(fileName);
updateTitle();
}
}
void MainWindow::loadConfigFromFile(const QString & fileName)
{
// save full path info of original file
QString absFileName = QFileInfo(fileName).absoluteFilePath();
// updates the current directory
updateConfigFileName(fileName);
// open the specified configuration file
m_expert->loadConfig(absFileName);
m_wizard->refresh();
updateLaunchButtonState();
m_modified = false;
updateTitle();
}
void MainWindow::saveConfig(const QString &fileName)
{
if (fileName.isEmpty()) return;
QFile f(fileName);
if (!f.open(QIODevice::WriteOnly | QIODevice::Text ))
{
QMessageBox::warning(this,
tr("Error saving"),
tr("Error: cannot open the file ")+fileName+tr(" for writing!\n")+
tr("Reason given: ")+f.error());
return;
}
QTextStream t(&f);
m_expert->writeConfig(t,false,false);
updateConfigFileName(fileName);
m_modified = false;
updateTitle();
}
bool MainWindow::saveConfig()
{
if (m_fileName.isEmpty())
{
return saveConfigAs();
}
else
{
saveConfig(m_fileName);
return true;
}
}
bool MainWindow::saveConfigAs()
{
QString fileName = QFileDialog::getSaveFileName(this, QString(),
m_workingDir->text()+QString::fromLatin1("/Doxyfile"));
if (fileName.isEmpty()) return false;
saveConfig(fileName);
return true;
}
void MainWindow::makeDefaults()
{
if (QMessageBox::question(this,tr("Use current setting at startup?"),
tr("Do you want to save the current settings "
"and use them next time Doxywizard starts?"),
QMessageBox::Save|
QMessageBox::Cancel)==QMessageBox::Save)
{
//printf("MainWindow:makeDefaults()\n");
m_expert->saveSettings(&m_settings);
m_settings.setValue(QString::fromLatin1("wizard/loadsettings"), true);
m_settings.sync();
}
}
void MainWindow::clearRecent()
{
if (QMessageBox::question(this,tr("Clear the list of recent files?"),
tr("Do you want to clear the list of recently "
"loaded configuration files?"),
QMessageBox::Yes|
QMessageBox::Cancel)==QMessageBox::Yes)
{
m_recentMenu->clear();
m_recentFiles.clear();
for (int i=0;i<MAX_RECENT_FILES;i++)
{
m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i),QString::fromLatin1(""));
}
m_clearRecent->setEnabled(false);
m_recentMenu->setEnabled(false);
m_settings.sync();
}
}
void MainWindow::resetToDefaults()
{
if (QMessageBox::question(this,tr("Reset settings to their default values?"),
tr("Do you want to revert all settings back "
"to their original values?"),
QMessageBox::Reset|
QMessageBox::Cancel)==QMessageBox::Reset)
{
//printf("MainWindow:resetToDefaults()\n");
m_expert->resetToDefaults();
m_settings.setValue(QString::fromLatin1("wizard/loadsettings"), false);
m_settings.sync();
m_modified = false;
updateTitle();
m_wizard->refresh();
}
}
void MainWindow::loadSettings()
{
QVariant geometry = m_settings.value(QString::fromLatin1("main/geometry"), QVariant::Invalid);
QVariant state = m_settings.value(QString::fromLatin1("main/state"), QVariant::Invalid);
QVariant wizState = m_settings.value(QString::fromLatin1("wizard/state"), QVariant::Invalid);
QVariant loadSettings = m_settings.value(QString::fromLatin1("wizard/loadsettings"), QVariant::Invalid);
QVariant workingDir = m_settings.value(QString::fromLatin1("wizard/workingdir"), QVariant::Invalid);
if (geometry !=QVariant::Invalid) restoreGeometry(geometry.toByteArray());
if (state !=QVariant::Invalid) restoreState (state.toByteArray());
if (wizState !=QVariant::Invalid) m_wizard->restoreState(wizState.toByteArray());
if (loadSettings!=QVariant::Invalid && loadSettings.toBool())
{
m_expert->loadSettings(&m_settings);
if (workingDir!=QVariant::Invalid && QDir(workingDir.toString()).exists())
{
setWorkingDir(workingDir.toString());
}
}
/* due to prepend use list in reversed order */
for (int i=MAX_RECENT_FILES;i>=0;i--)
{
QString entry = m_settings.value(QString::fromLatin1("recent/config%1").arg(i)).toString();
if (!entry.isEmpty() && QFileInfo(entry).exists())
{
addRecentFileList(entry);
}
}
updateRecentFile();
}
void MainWindow::saveSettings()
{
QSettings settings(QString::fromLatin1("Doxygen.org"), QString::fromLatin1("Doxywizard"));
m_settings.setValue(QString::fromLatin1("main/geometry"), saveGeometry());
m_settings.setValue(QString::fromLatin1("main/state"), saveState());
m_settings.setValue(QString::fromLatin1("wizard/state"), m_wizard->saveState());
m_settings.setValue(QString::fromLatin1("wizard/workingdir"), m_workingDir->text());
}
void MainWindow::selectTab(int id)
{
if (id==0) m_wizard->refresh();
else if (id==1) m_expert->refresh();
}
void MainWindow::selectRunTab()
{
m_tabs->setCurrentIndex(2);
}
void MainWindow::addRecentFile(const QString &fileName)
{
addRecentFileList(fileName);
updateRecentFile();
}
void MainWindow::addRecentFileList(const QString &fileName)
{
int i=m_recentFiles.indexOf(fileName);
if (i!=-1) m_recentFiles.removeAt(i);
// not found
if (m_recentFiles.count() < MAX_RECENT_FILES) // append
{
m_recentFiles.prepend(fileName);
}
else // add + drop last item
{
m_recentFiles.removeLast();
m_recentFiles.prepend(fileName);
}
m_clearRecent->setEnabled(m_recentFiles.count()>0);
m_recentMenu->setEnabled(m_recentFiles.count()>0);
m_settings.sync();
}
void MainWindow::updateRecentFile(void)
{
m_recentMenu->clear();
int i=0;
foreach( QString str, m_recentFiles )
{
m_recentMenu->addAction(str);
m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i++),str);
}
for (;i<MAX_RECENT_FILES;i++)
{
m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i),QString::fromLatin1(""));
}
m_clearRecent->setEnabled(m_recentFiles.count()>0);
m_recentMenu->setEnabled(m_recentFiles.count()>0);
m_settings.sync();
}
void MainWindow::openRecent(QAction *action)
{
if (discardUnsavedChanges(false))
{
loadConfigFromFile(action->text());
}
}
void MainWindow::runDoxygen()
{
if (!m_running)
{
QString doxygenPath;
#if defined(Q_OS_MACX)
doxygenPath = qApp->applicationDirPath()+QString::fromLatin1("/../Resources/");
qDebug() << tr("Doxygen path: ") << doxygenPath;
if ( !QFile(doxygenPath + QString::fromLatin1("doxygen")).exists() )
{
// No Doxygen binary in the resources, if there is a system Doxygen binary, use that instead
if ( QFile(QString::fromLatin1("/usr/local/bin/doxygen")).exists() )
{
doxygenPath = QString::fromLatin1("/usr/local/bin/");
}
else
{
qDebug() << tr("Can't find the doxygen command, make sure it's in your $$PATH");
doxygenPath = QString::fromLatin1("");
}
}
qDebug() << tr("Getting doxygen from: ") << doxygenPath;
#endif
m_runProcess->setReadChannel(QProcess::StandardOutput);
m_runProcess->setProcessChannelMode(QProcess::MergedChannels);
m_runProcess->setWorkingDirectory(m_workingDir->text());
QStringList env=QProcess::systemEnvironment();
// set PWD environment variable to m_workingDir
env.replaceInStrings(QRegExp(QString::fromLatin1("^PWD=(.*)"),Qt::CaseInsensitive),
QString::fromLatin1("PWD=")+m_workingDir->text());
m_runProcess->setEnvironment(env);
QStringList args;
QStringList runOptions = m_runOptions->text().split(QLatin1Char(' '),QString::SkipEmptyParts);
args << runOptions;
args << QString::fromLatin1("-b"); // make stdout unbuffered
args << QString::fromLatin1("-"); // read config from stdin
m_outputLog->clear();
text1 = QString::fromLatin1("");
m_runProcess->start(doxygenPath + QString::fromLatin1("doxygen"), args);
if (!m_runProcess->waitForStarted())
{
m_outputLog->append(APPQT(QString::fromLatin1("*** Failed to run doxygen\n")));
return;
}
QTextStream t(m_runProcess);
m_expert->writeConfig(t,false,false);
m_runProcess->closeWriteChannel();
if (m_runProcess->state() == QProcess::NotRunning)
{
m_outputLog->append(APPQT(QString::fromLatin1("*** Failed to run doxygen\n")));
}
else
{
m_saveLog->setEnabled(false);
m_running=true;
m_run->setText(tr("Stop doxygen"));
m_runStatus->setText(tr("Status: running"));
m_timer->start(1000);
}
}
else
{
m_running=false;
m_run->setText(tr("Run doxygen"));
m_runStatus->setText(tr("Status: not running"));
m_runProcess->kill();
m_timer->stop();
//updateRunnable(m_workingDir->text());
}
}
void MainWindow::readStdout()
{
if (m_running)
{
QByteArray data = m_runProcess->readAllStandardOutput();
QString text = QString::fromUtf8(data);
if (!text.isEmpty())
{
text1 += text;
m_outputLog->clear();
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
m_outputLog->append(APPQT(text1.toHtmlEscaped().trimmed()));
#else
m_outputLog->append(APPQT(Qt::escape(text1).trimmed()));
#endif
}
}
}
void MainWindow::runComplete()
{
if (m_running)
{
m_outputLog->append(APPQT(tr("*** Doxygen has finished\n")));
}
else
{
m_outputLog->append(APPQT(tr("*** Cancelled by user\n")));
}
m_outputLog->ensureCursorVisible();
m_run->setText(tr("Run doxygen"));
m_runStatus->setText(tr("Status: not running"));
m_running=false;
updateLaunchButtonState();
//updateRunnable(m_workingDir->text());
m_saveLog->setEnabled(true);
}
void MainWindow::updateLaunchButtonState()
{
m_launchHtml->setEnabled(m_expert->htmlOutputPresent(m_workingDir->text()));
#if 0
m_launchPdf->setEnabled(m_expert->pdfOutputPresent(m_workingDir->text()));
#endif
}
void MainWindow::showHtmlOutput()
{
QString indexFile = m_expert->getHtmlOutputIndex(m_workingDir->text());
QFileInfo fi(indexFile);
// TODO: the following doesn't seem to work with IE
#ifdef WIN32
//QString indexUrl(QString::fromLatin1("file:///"));
ShellExecute(NULL, L"open", (LPCWSTR)fi.absoluteFilePath().utf16(), NULL, NULL, SW_SHOWNORMAL);
#else
QString indexUrl(QString::fromLatin1("file://"));
indexUrl+=fi.absoluteFilePath();
QDesktopServices::openUrl(QUrl(indexUrl));
#endif
}
void MainWindow::saveLog()
{
QString fn = QFileDialog::getSaveFileName(this, tr("Save log file"),
m_workingDir->text()+
QString::fromLatin1("/doxygen_log.txt"));
if (!fn.isEmpty())
{
QFile f(fn);
if (f.open(QIODevice::WriteOnly))
{
QTextStream t(&f);
t << m_outputLog->toPlainText();
statusBar()->showMessage(tr("Output log saved"),messageTimeout);
}
else
{
QMessageBox::warning(0,tr("Warning"),
tr("Cannot open file ")+fn+tr(" for writing. Nothing saved!"),tr("ok"));
}
}
}
void MainWindow::showSettings()
{
QString text;
QTextStream t(&text);
if (m_showCondensedSettings->isChecked())
{
m_expert->writeConfig(t,true,true);
}
else
{
m_expert->writeConfig(t,true,false);
}
m_outputLog->clear();
m_outputLog->append(APPQT(text));
m_outputLog->ensureCursorVisible();
m_saveLog->setEnabled(true);
}
void MainWindow::configChanged()
{
m_modified = true;
updateTitle();
}
void MainWindow::updateTitle()
{
QString title = tr("Doxygen GUI frontend");
m_resetDefault->setEnabled(m_modified);
if (m_modified)
{
title+=QString::fromLatin1(" +");
}
if (!m_fileName.isEmpty())
{
title+=QString::fromLatin1(" (")+m_fileName+QString::fromLatin1(")");
}
setWindowTitle(title);
}
bool MainWindow::discardUnsavedChanges(bool saveOption)
{
if (m_modified)
{
QMessageBox::StandardButton button;
if (saveOption)
{
button = QMessageBox::question(this,
tr("Unsaved changes"),
tr("Unsaved changes will be lost! Do you want to save the configuration file?"),
QMessageBox::Save |
QMessageBox::Discard |
QMessageBox::Cancel
);
if (button==QMessageBox::Save)
{
return saveConfig();
}
}
else
{
button = QMessageBox::question(this,
tr("Unsaved changes"),
tr("Unsaved changes will be lost! Do you want to continue?"),
QMessageBox::Discard |
QMessageBox::Cancel
);
}
return button==QMessageBox::Discard;
}
return true;
}
void MainWindow::outputLogStart()
{
m_outputLogTextCount = 0;
m_outputLog->clear();
}
void MainWindow::outputLogText(QString text)
{
m_outputLogTextCount++;
m_outputLog->append(APPQT(text));
}
void MainWindow::outputLogFinish()
{
if (m_outputLogTextCount > 0)
{
selectRunTab();
}
m_outputLog->ensureCursorVisible();
m_saveLog->setEnabled(true);
}
//-----------------------------------------------------------------------
int main(int argc,char **argv)
{
QApplication a(argc,argv);
int locArgc = argc;
if (locArgc == 2)
{
if (!qstrcmp(argv[1],"--help"))
{
QMessageBox msgBox;
msgBox.setText(QString::fromLatin1("Usage: %1 [config file]").arg(QString::fromLatin1(argv[0])));
msgBox.exec();
exit(0);
}
else if (!qstrcmp(argv[1],"--version"))
{
QMessageBox msgBox;
if (!qstrcmp(qVersion(),QT_VERSION_STR))
{
msgBox.setText(QString::fromLatin1("Doxywizard version: %1, Qt version: %2").arg(QString::fromLatin1(getFullVersion()),QString::fromLatin1(QT_VERSION_STR)));
}
else
{
msgBox.setText(QString::fromLatin1("Doxywizard version: %1, Qt version: created with %2, running with %3").arg(QString::fromLatin1(getFullVersion()),QString::fromLatin1(QT_VERSION_STR),QString::fromLatin1(qVersion())));
}
msgBox.exec();
exit(0);
}
}
if (!qstrcmp(argv[1],"--debug") && ((locArgc == 2) || (locArgc == 3)))
{
DoxygenWizard::debugFlag = true;
locArgc--;
}
if (locArgc > 2)
{
QMessageBox msgBox;
msgBox.setText(QString::fromLatin1("Too many arguments specified\n\nUsage: %1 [config file]").arg(QString::fromLatin1(argv[0])));
msgBox.exec();
exit(1);
}
else
{
MainWindow &main = MainWindow::instance();
if (locArgc==2 && argv[argc-1][0]!='-') // name of config file as an argument
{
main.loadConfigFromFile(QString::fromLocal8Bit(argv[argc-1]));
}
main.show();
return a.exec();
}
}

120
addon/doxywizard/doxywizard.h Executable file
View File

@ -0,0 +1,120 @@
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef DOXYWIZARD_H
#define DOXYWIZARD_H
#include <QMainWindow>
#include <QSettings>
#include <QStringList>
class Expert;
class Wizard;
class QLabel;
class QCheckBox;
class QLineEdit;
class QPushButton;
class QTextBrowser;
class QMenu;
class QProcess;
class QTimer;
class QTabWidget;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
static MainWindow &instance();
void loadConfigFromFile(const QString &fileName);
void loadSettings();
void saveSettings();
void closeEvent(QCloseEvent *event);
QString configFileName() const { return m_fileName; }
void updateTitle();
// access routines for outputLog pane
void outputLogStart();
void outputLogText(QString text);
void outputLogFinish();
public slots:
void manual();
void about();
void openConfig();
bool saveConfig();
bool saveConfigAs();
void makeDefaults();
void resetToDefaults();
void selectTab(int);
void quit();
private slots:
void openRecent(QAction *action);
void selectWorkingDir();
void updateWorkingDir();
void runDoxygen();
void readStdout();
void runComplete();
void showHtmlOutput();
void saveLog();
void showSettings();
void configChanged();
void clearRecent();
void selectRunTab();
private:
MainWindow();
void saveConfig(const QString &fileName);
void addRecentFile(const QString &fileName);
void addRecentFileList(const QString &fileName);
void updateRecentFile(void);
void updateConfigFileName(const QString &fileName);
void setWorkingDir(const QString &dirName);
void updateLaunchButtonState();
bool discardUnsavedChanges(bool saveOption=true);
QLineEdit *m_workingDir;
QLineEdit *m_runOptions;
QPushButton *m_selWorkingDir;
QPushButton *m_run;
QPushButton *m_saveLog;
QCheckBox *m_showCondensedSettings;
QPushButton *m_launchHtml;
QPushButton *m_launchPdf;
QTextBrowser *m_outputLog;
QLabel *m_runStatus;
Expert *m_expert;
Wizard *m_wizard;
QString m_fileName;
QSettings m_settings;
QMenu *m_recentMenu;
QStringList m_recentFiles;
QAction *m_resetDefault;
QAction *m_clearRecent;
QProcess *m_runProcess;
QTimer *m_timer;
QTabWidget *m_tabs;
int m_outputLogTextCount = 0;
bool m_running;
bool m_modified;
};
/*! \brief This class serves as a namespace for global variables used by the doxygen wizard.
*
* All fields in this class are public and static, so they can be used directly.
*/
class DoxygenWizard
{
public:
static bool debugFlag;
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -0,0 +1,11 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file alias="config.xml">../../src/config.xml</file>
<file>images/add.png</file>
<file>images/del.png</file>
<file>images/file.png</file>
<file>images/folder.png</file>
<file>images/refresh.png</file>
<file>images/tunecolor.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "doxywizard.ico"

986
addon/doxywizard/expert.cpp Normal file
View File

@ -0,0 +1,986 @@
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#include "expert.h"
#include "inputbool.h"
#include "inputstring.h"
#include "inputint.h"
#include "inputstring.h"
#include "inputstrlist.h"
#include "config.h"
#include "version.h"
#include "configdoc.h"
#include "settings.h"
#include <QTreeWidget>
#include <QStackedWidget>
#include <QTextBrowser>
#include <QSplitter>
#include <QGridLayout>
#include <QPushButton>
#include <QScrollArea>
#include <QFile>
#include <QMessageBox>
#include <QSettings>
#include <QTextStream>
#include <QTextCodec>
#include <QFileInfo>
#define SA(x) QString::fromLatin1(x)
static QString convertToComment(const QString &s)
{
if (s.isEmpty())
{
return QString();
}
else
{
return SA("# ")+
s.trimmed().replace(SA("\n"),SA("\n# ")).replace(SA("# \n"), SA("#\n"))+
SA("\n");
}
}
void Expert::setHeader(const char *header)
{
m_header = SA(header);
}
void Expert::add(const char *name,const char *docs)
{
Input *opt = m_options[SA(name)];
if (opt)
{
opt->setTemplateDocs(SA(docs));
}
}
//------------------------------------------------------------------------------------
Expert::Expert()
{
m_treeWidget = new QTreeWidget;
m_treeWidget->setColumnCount(1);
m_topicStack = new QStackedWidget;
m_inShowHelp = false;
QFile file(SA(":/config.xml"));
QString err;
int errLine,errCol;
QDomDocument configXml;
if (file.open(QIODevice::ReadOnly))
{
if (!configXml.setContent(&file,false,&err,&errLine,&errCol))
{
QString msg = tr("Error parsing internal config.xml at line %1 column %2.\n%3").
arg(errLine).arg(errCol).arg(err);
QMessageBox::warning(this, tr("Error"), msg);
exit(1);
}
}
m_rootElement = configXml.documentElement();
createTopics(m_rootElement);
m_helper = new QTextBrowser;
m_helper->setReadOnly(true);
m_helper->setOpenExternalLinks(true);
m_splitter = new QSplitter(Qt::Vertical);
m_splitter->addWidget(m_treeWidget);
m_splitter->addWidget(m_helper);
QWidget *rightSide = new QWidget;
QGridLayout *grid = new QGridLayout(rightSide);
m_prev = new QPushButton(tr("Previous"));
m_prev->setEnabled(false);
m_next = new QPushButton(tr("Next"));
grid->addWidget(m_topicStack,0,0,1,2);
grid->addWidget(m_prev,1,0,Qt::AlignLeft);
grid->addWidget(m_next,1,1,Qt::AlignRight);
grid->setColumnStretch(0,1);
grid->setRowStretch(0,1);
addWidget(m_splitter);
addWidget(rightSide);
connect(m_next,SIGNAL(clicked()),SLOT(nextTopic()));
connect(m_prev,SIGNAL(clicked()),SLOT(prevTopic()));
addConfigDocs(this);
}
Expert::~Expert()
{
QHashIterator<QString,Input*> i(m_options);
while (i.hasNext())
{
i.next();
delete i.value();
}
}
void Expert::createTopics(const QDomElement &rootElem)
{
QList<QTreeWidgetItem*> items;
QDomElement childElem = rootElem.firstChildElement();
while (!childElem.isNull())
{
if (childElem.tagName()==SA("group"))
{
// Remove _ from a group name like: Source_Browser
QString name = childElem.attribute(SA("name")).replace(SA("_"),SA(" "));
QString setting = childElem.attribute(SA("setting"));
if (setting.isEmpty() || IS_SUPPORTED(setting.toLatin1()))
{
items.append(new QTreeWidgetItem((QTreeWidget*)0,QStringList(name)));
QWidget *widget = createTopicWidget(childElem);
m_topics[name] = widget;
m_topicStack->addWidget(widget);
}
}
childElem = childElem.nextSiblingElement();
}
m_treeWidget->setHeaderLabels(QStringList() << SA("Topics"));
m_treeWidget->insertTopLevelItems(0,items);
connect(m_treeWidget,
SIGNAL(currentItemChanged(QTreeWidgetItem *,QTreeWidgetItem *)),
this,
SLOT(activateTopic(QTreeWidgetItem *,QTreeWidgetItem *)));
}
static QString getDocsForNode(const QDomElement &child)
{
QString type = child.attribute(SA("type"));
QString docs = SA("");
// read documentation text
QDomElement docsVal = child.firstChildElement();
while (!docsVal.isNull())
{
if (docsVal.tagName()==SA("docs") &&
docsVal.attribute(SA("doxywizard")) != SA("0"))
{
for (QDomNode n = docsVal.firstChild(); !n.isNull(); n = n.nextSibling())
{
QDomText t = n.toText();
if (!t.isNull()) docs+=t.data();
}
docs += SA("<br/>");
}
docsVal = docsVal.nextSiblingElement();
}
// for an enum we list the values
if (type==SA("enum"))
{
docs += SA("<br/>");
docs += SA("Possible values are: ");
int numValues=0;
docsVal = child.firstChildElement();
while (!docsVal.isNull())
{
if (docsVal.tagName()==SA("value"))
{
numValues++;
}
docsVal = docsVal.nextSiblingElement();
}
int i=0;
docsVal = child.firstChildElement();
while (!docsVal.isNull())
{
if (docsVal.tagName()==SA("value"))
{
i++;
docs += SA("<code>") + docsVal.attribute(SA("name")) + SA("</code>");
QString desc = docsVal.attribute(SA("desc"));
if (!desc.isEmpty())
{
docs+= SA(" ")+desc;
}
if (i==numValues-1)
{
docs+=SA(" and ");
}
else if (i==numValues)
{
docs+=SA(".");
}
else
{
docs+=SA(", ");
}
}
docsVal = docsVal.nextSiblingElement();
}
docs+=SA("<br/>");
docs+=SA("<br/>");
docs+=SA(" The default value is: <code>")+
child.attribute(SA("defval"))+
SA("</code>.");
docs+= SA("<br/>");
}
else if (type==SA("int"))
{
docs+=SA("<br/>");
docs+=SA("Minimum value: ")+child.attribute(SA("minval"))+SA(", ");
docs+=SA("maximum value: ")+child.attribute(SA("maxval"))+SA(", ");
docs+=SA("default value: ")+child.attribute(SA("defval"))+SA(".");
docs+= SA("<br/>");
}
else if (type==SA("bool"))
{
docs+=SA("<br/>");
if (child.hasAttribute(SA("altdefval")))
{
docs+=SA(" The default value is: system dependent.");
}
else
{
QString defval = child.attribute(SA("defval"));
docs+=SA(" The default value is: <code>")+
(defval==SA("1")?SA("YES"):SA("NO"))+
SA("</code>.");
}
docs+= SA("<br/>");
}
else if (type==SA("list"))
{
if (child.attribute(SA("format"))==SA("string"))
{
int numValues = 0;
docsVal = child.firstChildElement();
while (!docsVal.isNull())
{
if (docsVal.tagName()==SA("value"))
{
QString showDocu = SA("");
if (docsVal.hasAttribute(SA("show_docu")))
{
showDocu = docsVal.attribute(SA("show_docu")).toLower();
}
if ((showDocu != SA("no")) && (docsVal.attribute(SA("name"))!=SA(""))) numValues++;
}
docsVal = docsVal.nextSiblingElement();
}
if (numValues>0)
{
int i = 0;
docsVal = child.firstChildElement();
while (!docsVal.isNull())
{
if (docsVal.tagName()==SA("value"))
{
QString showDocu = SA("");
if (docsVal.hasAttribute(SA("show_docu")))
{
showDocu = docsVal.attribute(SA("show_docu")).toLower();
}
if ((showDocu != SA("no")) && (docsVal.attribute(SA("name"))!=SA("")))
{
i++;
docs += SA("<code>") + docsVal.attribute(SA("name")) + SA("</code>");
QString desc = docsVal.attribute(SA("desc"));
if (desc != SA(""))
{
docs += SA(" ") + desc;
}
if (i==numValues-1)
{
docs += SA(" and ");
}
else if (i==numValues)
{
docs += SA(".");
}
else
{
docs += SA(", ");
}
}
}
docsVal = docsVal.nextSiblingElement();
}
}
// docs+= SA("<br/>");
}
}
else if (type==SA("string"))
{
QString defval = child.attribute(SA("defval"));
if (child.attribute(SA("format")) == SA("dir"))
{
if (defval != SA(""))
{
docs+=SA("<br/>");
docs += SA(" The default directory is: <code>") + defval + SA("</code>.");
docs += SA("<br/>");
}
}
else if (child.attribute(SA("format")) == SA("file"))
{
QString abspath = child.attribute(SA("abspath"));
if (defval != SA(""))
{
docs+=SA("<br/>");
if (abspath != SA("1"))
{
docs += SA(" The default file is: <code>") + defval + SA("</code>.");
}
else
{
docs += SA(" The default file (with absolute path) is: <code>") + defval + SA("</code>.");
}
docs += SA("<br/>");
}
else
{
if (abspath == SA("1"))
{
docs+=SA("<br/>");
docs += SA(" The file has to be specified with full path.");
docs += SA("<br/>");
}
}
}
else if (child.attribute(SA("format")) == SA("image"))
{
QString abspath = child.attribute(SA("abspath"));
if (defval != SA(""))
{
docs+=SA("<br/>");
if (abspath != SA("1"))
{
docs += SA(" The default image is: <code>") + defval + SA("</code>.");
}
else
{
docs += SA(" The default image (with absolute path) is: <code>") + defval + SA("</code>.");
}
docs += SA("<br/>");
}
else
{
if (abspath == SA("1"))
{
docs+=SA("<br/>");
docs += SA(" The image has to be specified with full path.");
docs += SA("<br/>");
}
}
}
else // if (child.attribute(SA("format")) == SA("string"))
{
if (defval != SA(""))
{
docs+=SA("<br/>");
docs += SA(" The default value is: <code>") + defval + SA("</code>.");
docs += SA("<br/>");
}
}
}
if (child.hasAttribute(SA("depends")))
{
QString dependsOn = child.attribute(SA("depends"));
docs+=SA("<br/>");
docs+= SA(" This tag requires that the tag \\ref cfg_");
docs+= dependsOn.toLower();
docs+= SA(" \"");
docs+= dependsOn.toUpper();
docs+= SA("\" is set to <code>YES</code>.");
}
// Remove / replace doxygen markup strings
// the regular expressions are hard to read so the intention will be given
// Note: see also configgen.py in the src directory for other doxygen parts
QRegExp regexp;
// remove \n at end and replace by a space
regexp.setPattern(SA("\\n$"));
docs.replace(regexp,SA(" "));
// remove <br> at end
regexp.setPattern(SA("<br> *$"));
docs.replace(regexp,SA(" "));
// \c word -> <code>word</code>; word ends with ')', ',', '.' or ' '
regexp.setPattern(SA("\\\\c[ ]+([^ \\)]+)\\)"));
docs.replace(regexp,SA("<code>\\1</code>)"));
regexp.setPattern(SA("\\\\c[ ]+([^ ,]+),"));
docs.replace(regexp,SA("<code>\\1</code>,"));
regexp.setPattern(SA("\\\\c[ ]+([^ \\.]+)\\."));
docs.replace(regexp,SA("<code>\\1</code>."));
regexp.setPattern(SA("\\\\c[ ]+([^ ]+) "));
docs.replace(regexp,SA("<code>\\1</code> "));
// `word` -> <code>word</code>
docs.replace(SA("``"),SA(""));
regexp.setPattern(SA("`([^`]+)`"));
docs.replace(regexp,SA("<code>\\1</code>"));
// \ref key "desc" -> <code>desc</code>
regexp.setPattern(SA("\\\\ref[ ]+[^ ]+[ ]+\"([^\"]+)\""));
docs.replace(regexp,SA("<code>\\1</code> "));
//\ref specials
// \ref <key> -> description
regexp.setPattern(SA("\\\\ref[ ]+doxygen_usage"));
docs.replace(regexp,SA("\"Doxygen usage\""));
regexp.setPattern(SA("\\\\ref[ ]+extsearch"));
docs.replace(regexp,SA("\"External Indexing and Searching\""));
regexp.setPattern(SA("\\\\ref[ ]+external"));
docs.replace(regexp,SA("\"Linking to external documentation\""));
regexp.setPattern(SA("\\\\ref[ ]+formulas"));
docs.replace(regexp,SA("\"Including formulas\""));
// fallback for not handled
docs.replace(SA("\\\\ref"),SA(""));
// \b word -> <b>word<\b>
regexp.setPattern(SA("\\\\b[ ]+([^ ]+) "));
docs.replace(regexp,SA("<b>\\1</b> "));
// \e word -> <em>word<\em>
regexp.setPattern(SA("\\\\e[ ]+([^ ]+) "));
docs.replace(regexp,SA("<em>\\1</em> "));
// \note -> <br>Note:
// @note -> <br>Note:
docs.replace(SA("\\note"),SA("<br>Note:"));
docs.replace(SA("@note"),SA("<br>Note:"));
// \#include -> #include
// \#undef -> #undef
docs.replace(SA("\\#include"),SA("#include"));
docs.replace(SA("\\#undef"),SA("#undef"));
// -# -> <br>-
// " - " -> <br>-
docs.replace(SA("-#"),SA("<br>-"));
docs.replace(SA(" - "),SA("<br>-"));
// \verbatim -> <pre>
// \endverbatim -> </pre>
docs.replace(SA("\\verbatim"),SA("<pre>"));
docs.replace(SA("\\endverbatim"),SA("</pre>"));
// \sa -> <br>See also:
// \par -> <br>
docs.replace(SA("\\sa"),SA("<br>See also:"));
docs.replace(SA("\\par"),SA("<br>"));
// 2xbackslash -> backslash
// \@ -> @
docs.replace(SA("\\\\"),SA("\\"));
docs.replace(SA("\\@"),SA("@"));
// \& -> &
// \$ -> $
docs.replace(SA("\\&"),SA("&"));
docs.replace(SA("\\$"),SA("$"));
// \< -> &lt;
// \> -> &gt;
docs.replace(SA("\\<"),SA("&lt;"));
docs.replace(SA("\\>"),SA("&gt;"));
regexp.setPattern(SA(" (http:[^ \\)]*)([ \\)])"));
docs.replace(regexp,SA(" <a href=\"\\1\">\\1</a>\\2"));
// LaTeX name as formula -> LaTeX
regexp.setPattern(SA("\\\\f\\$\\\\mbox\\{\\\\LaTeX\\}\\\\f\\$"));
docs.replace(regexp,SA("LaTeX"));
// Other formula's (now just 2) so explicitly mentioned.
regexp.setPattern(SA("\\\\f\\$2\\^\\{\\(16\\+\\\\mbox\\{LOOKUP\\\\_CACHE\\\\_SIZE\\}\\)\\}\\\\f\\$"));
docs.replace(regexp,SA("2^(16+LOOKUP_CACHE_SIZE)"));
regexp.setPattern(SA("\\\\f\\$2\\^\\{16\\} = 65536\\\\f\\$"));
docs.replace(regexp,SA("2^16=65536"));
return docs.trimmed();
}
QWidget *Expert::createTopicWidget(QDomElement &elem)
{
QScrollArea *area = new QScrollArea;
QWidget *topic = new QWidget;
QGridLayout *layout = new QGridLayout(topic);
QDomElement child = elem.firstChildElement();
int row=0;
while (!child.isNull())
{
QString setting = child.attribute(SA("setting"));
if (setting.isEmpty() || IS_SUPPORTED(setting.toLatin1()))
{
QString type = child.attribute(SA("type"));
QString docs = getDocsForNode(child);
if (type==SA("bool"))
{
InputBool *boolOption =
new InputBool(
layout,row,
child.attribute(SA("id")),
child.attribute(SA("defval"))==SA("1"),
docs
);
m_options.insert(
child.attribute(SA("id")),
boolOption
);
connect(boolOption,SIGNAL(showHelp(Input*)),SLOT(showHelp(Input*)));
connect(boolOption,SIGNAL(changed()),SIGNAL(changed()));
}
else if (type==SA("string"))
{
InputString::StringMode mode;
QString format = child.attribute(SA("format"));
if (format==SA("dir"))
{
mode = InputString::StringDir;
}
else if (format==SA("file"))
{
mode = InputString::StringFile;
}
else if (format==SA("image"))
{
mode = InputString::StringImage;
}
else // format=="string"
{
mode = InputString::StringFree;
}
InputString *stringOption =
new InputString(
layout,row,
child.attribute(SA("id")),
child.attribute(SA("defval")),
mode,
docs,
child.attribute(SA("abspath"))
);
m_options.insert(
child.attribute(SA("id")),
stringOption
);
connect(stringOption,SIGNAL(showHelp(Input*)),SLOT(showHelp(Input*)));
connect(stringOption,SIGNAL(changed()),SIGNAL(changed()));
}
else if (type==SA("enum"))
{
InputString *enumList = new InputString(
layout,row,
child.attribute(SA("id")),
child.attribute(SA("defval")),
InputString::StringFixed,
docs
);
QDomElement enumVal = child.firstChildElement();
while (!enumVal.isNull())
{
if (enumVal.tagName()==SA("value"))
{
enumList->addValue(enumVal.attribute(SA("name")));
}
enumVal = enumVal.nextSiblingElement();
}
enumList->setDefault();
m_options.insert(child.attribute(SA("id")),enumList);
connect(enumList,SIGNAL(showHelp(Input*)),SLOT(showHelp(Input*)));
connect(enumList,SIGNAL(changed()),SIGNAL(changed()));
}
else if (type==SA("int"))
{
InputInt *intOption =
new InputInt(
layout,row,
child.attribute(SA("id")),
child.attribute(SA("defval")).toInt(),
child.attribute(SA("minval")).toInt(),
child.attribute(SA("maxval")).toInt(),
docs
);
m_options.insert(
child.attribute(SA("id")),
intOption
);
connect(intOption,SIGNAL(showHelp(Input*)),SLOT(showHelp(Input*)));
connect(intOption,SIGNAL(changed()),SIGNAL(changed()));
}
else if (type==SA("list"))
{
InputStrList::ListMode mode;
QString format = child.attribute(SA("format"));
if (format==SA("dir"))
{
mode = InputStrList::ListDir;
}
else if (format==SA("file"))
{
mode = InputStrList::ListFile;
}
else if (format==SA("filedir"))
{
mode = InputStrList::ListFileDir;
}
else // format=="string"
{
mode = InputStrList::ListString;
}
QStringList sl;
QDomElement listVal = child.firstChildElement();
while (!listVal.isNull())
{
if (listVal.tagName()==SA("value"))
{
sl.append(listVal.attribute(SA("name")));
}
listVal = listVal.nextSiblingElement();
}
InputStrList *listOption =
new InputStrList(
layout,row,
child.attribute(SA("id")),
sl,
mode,
docs
);
m_options.insert(
child.attribute(SA("id")),
listOption
);
connect(listOption,SIGNAL(showHelp(Input*)),SLOT(showHelp(Input*)));
connect(listOption,SIGNAL(changed()),SIGNAL(changed()));
}
else if (type==SA("obsolete"))
{
// ignore
}
else // should not happen
{
printf("Unsupported type %s\n",qPrintable(child.attribute(SA("type"))));
}
} // IS_SUPPORTED
child = child.nextSiblingElement();
}
// compute dependencies between options
child = elem.firstChildElement();
while (!child.isNull())
{
QString setting = child.attribute(SA("setting"));
QString dependsOn = child.attribute(SA("depends"));
QString id = child.attribute(SA("id"));
if (!dependsOn.isEmpty() &&
(setting.isEmpty() || IS_SUPPORTED(setting.toLatin1())))
{
Input *parentOption = m_options[dependsOn];
if (parentOption==0)
{
printf("%s has depends=%s that is not valid\n",
qPrintable(id),qPrintable(dependsOn));
}
Input *thisOption = m_options[id];
Q_ASSERT(parentOption);
Q_ASSERT(thisOption);
if (parentOption && thisOption)
{
//printf("Adding dependency '%s' (%p)->'%s' (%p)\n",
// qPrintable(dependsOn),parentOption,
// qPrintable(id),thisOption);
parentOption->addDependency(thisOption);
}
}
child = child.nextSiblingElement();
}
// set initial dependencies
QHashIterator<QString,Input*> i(m_options);
while (i.hasNext())
{
i.next();
if (i.value())
{
i.value()->updateDependencies();
}
}
layout->setRowStretch(row,1);
layout->setColumnStretch(1,2);
layout->setSpacing(5);
topic->setLayout(layout);
area->setWidget(topic);
area->setWidgetResizable(true);
return area;
}
void Expert::activateTopic(QTreeWidgetItem *item,QTreeWidgetItem *)
{
if (item)
{
QWidget *w = m_topics[item->text(0)];
m_topicStack->setCurrentWidget(w);
m_prev->setEnabled(m_topicStack->currentIndex()!=0);
m_next->setEnabled(true);
}
}
void Expert::loadSettings(QSettings *s)
{
QHashIterator<QString,Input*> i(m_options);
while (i.hasNext())
{
i.next();
QVariant var = s->value(SA("config/")+i.key());
if (i.value())
{
//printf("Loading key %s: type=%d value='%s'\n",qPrintable(i.key()),var.type(),qPrintable(var.toString()));
i.value()->value() = var;
i.value()->update();
}
}
}
void Expert::saveSettings(QSettings *s)
{
QHashIterator<QString,Input*> i(m_options);
while (i.hasNext())
{
i.next();
//printf("Saving key %s: type=%d value='%s'\n",qPrintable(i.key()),i.value()->value().type(),qPrintable(i.value()->value().toString()));
if (i.value())
{
s->setValue(SA("config/")+i.key(),i.value()->value());
}
}
}
void Expert::loadConfig(const QString &fileName)
{
//printf("Expert::loadConfig(%s)\n",qPrintable(fileName));
parseConfig(fileName,m_options);
}
void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec,
bool brief,bool condensed)
{
if (!brief)
{
t << endl;
}
if (!condensed)
{
t << "#---------------------------------------------------------------------------" << endl;
t << "# " << elem.attribute(SA("docs")) << endl;
t << "#---------------------------------------------------------------------------" << endl;
}
// write options...
QDomElement childElem = elem.firstChildElement();
while (!childElem.isNull())
{
QString setting = childElem.attribute(SA("setting"));
QString type = childElem.attribute(SA("type"));
QString name = childElem.attribute(SA("id"));
if (setting.isEmpty() || IS_SUPPORTED(setting.toLatin1()))
{
QHash<QString,Input*>::const_iterator i = m_options.find(name);
if (i!=m_options.end())
{
Input *option = i.value();
if (option && !brief)
{
t << endl;
t << convertToComment(option->templateDocs());
t << endl;
}
bool toPrint = true;
if (option && condensed) toPrint = !option->isDefault();
if (toPrint)
{
t << name.leftJustified(MAX_OPTION_LENGTH) << "=";
if (option && !option->isEmpty())
{
t << " ";
option->writeValue(t,codec);
}
t << endl;
}
}
}
childElem = childElem.nextSiblingElement();
}
}
bool Expert::writeConfig(QTextStream &t,bool brief, bool condensed)
{
// write global header
t << "# Doxyfile " << getDoxygenVersion() << endl << endl;
if (!brief && !condensed)
{
t << convertToComment(m_header);
}
QTextCodec *codec = 0;
Input *option = m_options[QString::fromLatin1("DOXYFILE_ENCODING")];
if (option)
{
codec = QTextCodec::codecForName(option->value().toString().toLatin1());
if (codec==0) // fallback: use UTF-8
{
codec = QTextCodec::codecForName("UTF-8");
}
}
QDomElement childElem = m_rootElement.firstChildElement();
while (!childElem.isNull())
{
if (childElem.tagName()==SA("group"))
{
saveTopic(t,childElem,codec,brief,condensed);
}
childElem = childElem.nextSiblingElement();
}
return true;
}
QByteArray Expert::saveInnerState () const
{
return m_splitter->saveState();
}
bool Expert::restoreInnerState ( const QByteArray & state )
{
return m_splitter->restoreState(state);
}
void Expert::showHelp(Input *option)
{
if (!m_inShowHelp)
{
m_inShowHelp = true;
m_helper->setText(
QString::fromLatin1("<qt><b>")+option->id()+
QString::fromLatin1("</b><br>")+
QString::fromLatin1("<br/>")+
option->docs().
replace(QChar::fromLatin1('\n'),QChar::fromLatin1(' '))+
QString::fromLatin1("</qt>")
);
m_inShowHelp = false;
}
}
void Expert::nextTopic()
{
if (m_topicStack->currentIndex()+1==m_topicStack->count()) // last topic
{
done();
}
else
{
m_topicStack->setCurrentIndex(m_topicStack->currentIndex()+1);
m_next->setEnabled(m_topicStack->count()!=m_topicStack->currentIndex()+1);
m_prev->setEnabled(m_topicStack->currentIndex()!=0);
m_treeWidget->setCurrentItem(m_treeWidget->invisibleRootItem()->child(m_topicStack->currentIndex()));
}
}
void Expert::prevTopic()
{
m_topicStack->setCurrentIndex(m_topicStack->currentIndex()-1);
m_next->setEnabled(m_topicStack->count()!=m_topicStack->currentIndex()+1);
m_prev->setEnabled(m_topicStack->currentIndex()!=0);
m_treeWidget->setCurrentItem(m_treeWidget->invisibleRootItem()->child(m_topicStack->currentIndex()));
}
void Expert::resetToDefaults()
{
//printf("Expert::makeDefaults()\n");
QHashIterator<QString,Input*> i(m_options);
while (i.hasNext())
{
i.next();
if (i.value())
{
i.value()->reset();
}
}
}
static bool stringVariantToBool(const QVariant &v)
{
QString s = v.toString().toLower();
return s==QString::fromLatin1("yes") || s==QString::fromLatin1("true") || s==QString::fromLatin1("1");
}
static bool getBoolOption(
const QHash<QString,Input*>&model,const QString &name)
{
Input *option = model[name];
Q_ASSERT(option!=0);
return stringVariantToBool(option->value());
}
static QString getStringOption(
const QHash<QString,Input*>&model,const QString &name)
{
Input *option = model[name];
Q_ASSERT(option!=0);
return option->value().toString();
}
bool Expert::htmlOutputPresent(const QString &workingDir) const
{
bool generateHtml = getBoolOption(m_options,QString::fromLatin1("GENERATE_HTML"));
if (!generateHtml || workingDir.isEmpty()) return false;
QString indexFile = getHtmlOutputIndex(workingDir);
QFileInfo fi(indexFile);
return fi.exists() && fi.isFile();
}
QString Expert::getHtmlOutputIndex(const QString &workingDir) const
{
QString outputDir = getStringOption(m_options,QString::fromLatin1("OUTPUT_DIRECTORY"));
QString htmlOutputDir = getStringOption(m_options,QString::fromLatin1("HTML_OUTPUT"));
//printf("outputDir=%s\n",qPrintable(outputDir));
//printf("htmlOutputDir=%s\n",qPrintable(htmlOutputDir));
QString indexFile = workingDir;
if (QFileInfo(outputDir).isAbsolute()) // override
{
indexFile = outputDir;
}
else // append
{
indexFile += QString::fromLatin1("/")+outputDir;
}
if (QFileInfo(htmlOutputDir).isAbsolute()) // override
{
indexFile = htmlOutputDir;
}
else // append
{
indexFile += QString::fromLatin1("/")+htmlOutputDir;
}
indexFile+=QString::fromLatin1("/index.html");
return indexFile;
}
bool Expert::pdfOutputPresent(const QString &workingDir) const
{
bool generateLatex = getBoolOption(m_options,QString::fromLatin1("GENERATE_LATEX"));
bool pdfLatex = getBoolOption(m_options,QString::fromLatin1("USE_PDFLATEX"));
if (!generateLatex || !pdfLatex) return false;
QString latexOutput = getStringOption(m_options,QString::fromLatin1("LATEX_OUTPUT"));
QString indexFile;
if (QFileInfo(latexOutput).isAbsolute())
{
indexFile = latexOutput+QString::fromLatin1("/refman.pdf");
}
else
{
indexFile = workingDir+QString::fromLatin1("/")+
latexOutput+QString::fromLatin1("/refman.pdf");
}
QFileInfo fi(indexFile);
return fi.exists() && fi.isFile();
}
void Expert::refresh()
{
m_treeWidget->setCurrentItem(m_treeWidget->invisibleRootItem()->child(0));
}

86
addon/doxywizard/expert.h Normal file
View File

@ -0,0 +1,86 @@
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef EXPERT_H
#define EXPERT_H
#include <QSplitter>
#include <QDomElement>
#include <QHash>
#include "docintf.h"
class QTreeWidget;
class QTreeWidgetItem;
class QStackedWidget;
class QSettings;
class QTextBrowser;
class QTextCodec;
class QPushButton;
class Input;
class Expert : public QSplitter, public DocIntf
{
Q_OBJECT
public:
Expert();
~Expert();
void loadSettings(QSettings *);
void saveSettings(QSettings *);
void loadConfig(const QString &fileName);
bool writeConfig(QTextStream &t,bool brief,bool condensed);
QByteArray saveInnerState () const;
bool restoreInnerState ( const QByteArray & state );
const QHash<QString,Input*> &modelData() const { return m_options; }
void resetToDefaults();
bool htmlOutputPresent(const QString &workingDir) const;
bool pdfOutputPresent(const QString &workingDir) const;
QString getHtmlOutputIndex(const QString &workingDir) const;
// DocIntf methods
void setHeader(const char *name);
void add(const char *name,const char *doc);
public slots:
void activateTopic(QTreeWidgetItem *,QTreeWidgetItem *);
QWidget *createTopicWidget(QDomElement &elem);
void refresh();
private slots:
void showHelp(Input *);
void nextTopic();
void prevTopic();
signals:
void changed();
void done();
private:
void createTopics(const QDomElement &);
void saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec,bool brief,bool dondensed);
QSplitter *m_splitter;
QTextBrowser *m_helper;
QTreeWidget *m_treeWidget;
QStackedWidget *m_topicStack;
QHash<QString,QWidget *> m_topics;
QHash<QString,QObject *> m_optionWidgets;
QHash<QString,Input *> m_options;
QPushButton *m_next;
QPushButton *m_prev;
QDomElement m_rootElement;
bool m_inShowHelp;
QString m_header;
};
#endif

View File

@ -0,0 +1,45 @@
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
*/
#ifndef HELPLABEL_H
#define HELPLABEL_H
#include <QLabel>
#include <QMenu>
class HelpLabel : public QLabel
{
Q_OBJECT
public:
HelpLabel(const QString &text) : QLabel(text)
{ setContextMenuPolicy(Qt::CustomContextMenu);
connect(this,SIGNAL(customContextMenuRequested(const QPoint&)),
this,SLOT(showMenu(const QPoint&)));
}
signals:
void enter();
void reset();
private slots:
void showMenu(const QPoint &p)
{
QMenu menu(this);
QAction *a = menu.addAction(tr("Reset to default"));
if (menu.exec(mapToGlobal(p))==a)
{
reset();
}
}
protected:
void enterEvent( QEvent * event ) { enter(); QLabel::enterEvent(event); }
};
#endif

BIN
addon/doxywizard/images/add.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
addon/doxywizard/images/del.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
addon/doxywizard/images/file.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Some files were not shown because too many files have changed in this diff Show More