Import Upstream version 1.9.1
|
@ -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
|
|
@ -0,0 +1,5 @@
|
|||
# See https://editorconfig.org/ for more information.
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
|
@ -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.
|
|
@ -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'
|
|
@ -0,0 +1,20 @@
|
|||
*~
|
||||
.*sw?
|
||||
\#*
|
||||
.DS_Store
|
||||
|
||||
*.rej
|
||||
*.orig
|
||||
|
||||
*.pro
|
||||
/packages/rpm/doxygen.spec
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
/doxygen_docs
|
||||
/doxygen.tag
|
||||
/build*
|
||||
|
||||
tags
|
||||
|
||||
.idea
|
|
@ -0,0 +1 @@
|
|||
debian/patches
|
|
@ -0,0 +1 @@
|
|||
series
|
|
@ -0,0 +1 @@
|
|||
2
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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}"
|
||||
)
|
|
@ -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
|
|
@ -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}"
|
||||
)
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
@ -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).
|
|
@ -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
|
|
@ -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}"
|
||||
)
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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'
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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 ä 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.
|
||||
|
|
@ -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.
|
|
@ -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)
|
|
@ -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 ()
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(examples)
|
||||
add_subdirectory(test)
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
add_subdirectory(metrics)
|
|
@ -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}
|
||||
)
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
#include "basehandler.h"
|
||||
|
||||
QXmlLocator * LocatorContainer::s_theLocator=0;
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef _DEBUG_H
|
||||
#define _DEBUG_H
|
||||
|
||||
void debug(int level,const char *msg,...);
|
||||
void setDebugLevel(int level);
|
||||
|
||||
#endif
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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}
|
||||
)
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
|
@ -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.
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
|
@ -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>
|
|
@ -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).
|
|
@ -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);
|
||||
}
|
|
@ -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:])
|
|
@ -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)
|
|
@ -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,">",">");
|
||||
replace_all(result,"<","<");
|
||||
replace_all(result,"'","'");
|
||||
replace_all(result,""","\"");
|
||||
replace_all(result,"&","&");
|
||||
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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
|
@ -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.
|
||||
|
|
@ -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
|
|
@ -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"
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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>© 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();
|
||||
}
|
||||
}
|
|
@ -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
|
After Width: | Height: | Size: 82 KiB |
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
IDI_ICON1 ICON DISCARDABLE "doxywizard.ico"
|
|
@ -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("$"));
|
||||
// \< -> <
|
||||
// \> -> >
|
||||
docs.replace(SA("\\<"),SA("<"));
|
||||
docs.replace(SA("\\>"),SA(">"));
|
||||
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));
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 77 KiB |