release version 22.4

use 22.4.Summer as release version
This commit is contained in:
xiaoyifang 2022-04-01 20:21:38 +08:00
commit 15926efd95
580 changed files with 14048 additions and 45234 deletions

View file

@ -1,18 +1,28 @@
# Format Style Options - Created with Clang Power Tools
---
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: true
BasedOnStyle: LLVM
BinPackArguments: false
BinPackParameters: false
AlignAfterOpenBracket: Align
AlignEscapedNewlines: Left
AllowAllArgumentsOnNextLine: 'false'
AllowShortBlocksOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
BinPackArguments: 'false'
BinPackParameters: 'false'
BreakBeforeBraces: Allman
BreakConstructorInitializers: AfterColon
ColumnLimit: 160
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth : 2
ContinuationIndentWidth: 2
MaxEmptyLinesToKeep: 2
ColumnLimit: '120'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
ConstructorInitializerIndentWidth: '2'
ContinuationIndentWidth: '2'
MaxEmptyLinesToKeep: '1'
PointerAlignment: Middle
SpacesInAngles: true
SpacesInParentheses: true
SortIncludes: 'false'
SortUsingDeclarations: 'false'
SpaceBeforeParens: Never
SpacesInAngles: 'true'
SpacesInParentheses: 'true'
SpacesInSquareBrackets: 'true'
UseTab: Never
AlignConsecutiveAssignments: AcrossComments
...

View file

@ -27,6 +27,7 @@ function Main() {
New-Item -ItemType Directory $archiveName
New-Item -ItemType Directory $archiveName\locale
New-Item -ItemType Directory $archiveName\opencc
# 拷贝exe
Copy-Item release\$targetName $archiveName\
Write-Host "copy item finished..."
@ -43,13 +44,19 @@ function Main() {
Write-Host "copy redist dll..."
Copy-Item "LICENSE.txt" $archiveName\
Write-Host "copy license.."
Copy-Item "opencc\*" $archiveName\opencc\
Write-Host "opencc config files.."
# 拷贝WinSDK dll
$sdkDll="{0}Redist\{1}ucrt\DLLs\{2}\*.dll" -f $env:winSdkDir.Trim(),$env:winSdkVer.Trim(),$env:msvcArch
Write-Host "copy sdk dll$($sdkDll)"
Copy-Item $sdkDll $archiveName\
Copy-Item winlibs\lib\msvc\*.dll $archiveName\
Copy-Item locale\*.qm $archiveName\locale\
# Copy-Item qtsingleapplication\lib\*.dll $archiveName\
Write-Host "copy qwebengine zh_CN translation"
Copy-Item thirdparty\qwebengine_ts\*.qm $archiveName\locale\
$webengineqm="{0}\translations\qtwebengine_*.qm" -f $env:QTDIR.Trim()
Write-Host "copy qtwebengine qm from $($webengineqm)"
Copy-Item $webengineqm $archiveName\locale\
Write-Host "compress zip..."
# 打包zip
Compress-Archive -Path $archiveName -DestinationPath $archiveName'.zip'

51
.github/workflows/AutoTag.yml vendored Normal file
View file

@ -0,0 +1,51 @@
name: AutoTag
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_dispatch:
push:
branches:
- dev
- master
# - staged
paths-ignore:
- 'docs/**'
- ".github/**"
- "howto/**"
- "*.md"
- ".clang-format"
pull_request:
branches:
- dev
- master
# - staged
paths-ignore:
- 'docs/**'
- ".github/**"
- "howto/**"
- "*.md"
jobs:
build:
name: Build
runs-on: ubuntu-latest
env:
version: 22.4.Summer
# 步骤
steps:
- uses: actions/checkout@v3
- name: set git short sha
id: git
run: |
echo "::set-output name=sha_short::$(git rev-parse --short=8 HEAD)"
- name: Bump version and push tag
id: tag_version
uses: mathieudutour/github-tag-action@v6.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
custom_tag: ${{env.version}}-${{ steps.git.outputs.sha_short }}

View file

@ -1,84 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ dev ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ dev ]
schedule:
- cron: '40 15 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ${{ matrix.os }}
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp', 'javascript' ]
os: [ubuntu-20.04]
qt_ver: [5.15.2]
qt_arch: [gcc_64]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Install Qt
uses: jurplel/install-qt-action@v2.13.0
with:
version: ${{ matrix.qt_ver }}
cached: 'false'
modules: qtwebengine
- name: ubuntu install thirdparty dependencies
run: |
sudo apt-get install git pkg-config build-essential qt5-qmake
sudo apt-get install libvorbis-dev zlib1g-dev libhunspell-dev x11proto-record-dev
sudo apt-get install qtdeclarative5-dev libxtst-dev liblzo2-dev libbz2-dev
sudo apt-get install libao-dev libavutil-dev libavformat-dev libtiff5-dev libeb16-dev
sudo apt-get install libqt5webkit5-dev libqt5svg5-dev libqt5x11extras5-dev qttools5-dev
sudo apt-get install qttools5-dev-tools qtmultimedia5-dev libqt5multimedia5-plugins libopencc-dev libzstd-dev
sudo ln -sf /usr/bin/x86_64-linux-gnu-ld.gold /usr/bin/ld
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
- run: |
qmake CONFIG+=release PREFIX=/usr CONFIG+=zim_support CONFIG+=chinese_conversion_support
make INSTALL_ROOT=appdir -j`nproc` ; # find appdir/
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

123
.github/workflows/macos-6.2.yml vendored Normal file
View file

@ -0,0 +1,123 @@
name: macos-6.2
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_run:
workflows: [AutoTag]
types: [completed]
workflow_dispatch:
# push:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
# - ".clang-format"
# pull_request:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-11]
qt_ver: [6.2.3]
qt_arch: [clang_64]
env:
targetName: GoldenDict
version: 22.4.Summer
steps:
# macos 11.0 默认环境变了,要指定
- name: prepare env
if: ${{ matrix.os == 'macos-11' }}
run: |
softwareupdate --all --install --force
sudo xcode-select --print-path
sudo xcode-select --switch /Library/Developer/CommandLineTools
- uses: actions/setup-python@v3
with:
python-version: '3.9'
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
cached: 'false'
modules: qtwebengine qtwebchannel qtpositioning qt5compat qtmultimedia
setup-python: 'false'
py7zrversion: '==0.18.1'
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: build macos
run: |
wget ftp://ftp.sra.co.jp/pub/misc/eb/eb-4.4.3.tar.bz2
tar xvjf eb-4.4.3.tar.bz2
cd eb-4.4.3 && ./configure && make -j 8 && sudo make install && cd ..
#brew install qt # or use official offline installer
brew install opencc libao hunspell ffmpeg@5 libtiff xz lzo libogg libvorbis zstd
qmake CONFIG+=release CONFIG+=zim_support CONFIG+=chinese_conversion_support
make
# 打包
- name: package
run: |
macdeployqt ${targetName}.app -qmldir=. -verbose=1 -dmg
otool -L GoldenDict.app/Contents/MacOS/GoldenDict
- name: Set outputs
id: vars
run: |
echo "::set-output name=sha_short::$(git rev-parse --short=8 HEAD)"
echo "::set-output name=release_date::$(date +'%Y%m%d')"
echo "::set-output name=release_time::$(date +'%H%M%S')"
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
echo "previousTag : $previousTag"
CHANGELOG="$(git log --oneline --no-decorate $previousTag..HEAD)"
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
# tag 上传Release
- name: uploadRelease
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.targetName }}.dmg
asset_name: ${{ matrix.qt_ver }}-${{ env.targetName }}_${{ matrix.os }}_${{ steps.vars.outputs.sha_short }}.dmg
tag: v${{env.version}}-${{ steps.vars.outputs.sha_short }}
overwrite: true
release_name: win-linux-macos-${{steps.vars.outputs.release_date}}
prerelease: false
body: |
release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
branch: ${{ github.ref_name }}
commit: ${{ steps.vars.outputs.sha_short }}
Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
Windows built with: msvc64 Visual studio 2019
# goldendict.exe can not used alone
if you have a previous version. replace this maybe ok. if not ,download the whole bundle.
AppImage built with: Ubuntu-20.04 ,latest gcc
macos built with: macos-10.15,macos-11.0,clang_64 x86_64(Intel Kind)
auto built by github action. use on your on risk:-)
CHANGES:
${{ steps.vars.outputs.COMMIT_SUMMARY }}

127
.github/workflows/macos-m1.yml vendored Normal file
View file

@ -0,0 +1,127 @@
name: macos-m1
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_dispatch:
# push:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
# - ".clang-format"
# pull_request:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-11]
qt_ver: [6.2.2]
qt_arch: [clang_64]
env:
targetName: GoldenDict
steps:
- name: prepare env
run: |
softwareupdate --all --install --force
sudo xcode-select --switch /Applications/Xcode.app
sudo xcode-select --print-path
#sudo xcode-select --switch /Library/Developer/CommandLineTools
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
cached: 'false'
modules: qtwebengine qtwebchannel qtpositioning qt5compat qtmultimedia
setup-python: 'false'
- uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Set outputs
id: githash
run: |
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: build macos
run: |
brew install pcre2 harfbuzz freetype
brew install cmake ninja python
brew install automake
brew install autoconf
brew install libtool
git clone https://github.com/xiph/vorbis.git
cd vorbis
./autogen.sh
./configure
make
sudo make install
cd ..
brew install opencc
brew install ffmpeg@5
#brew reinstall $(brew deps ffmpeg) ffmpeg
brew install libao
brew install libiconv
brew install lzo
brew install libogg
brew install zstd
brew install libtiff
#brew install libvorbis --force
#brew link libvorbis --force
brew install hunspell
# brew install qt@6
brew install pkg-config
# CONFIG+=chinese_conversion_support
#file /usr/local/lib/libzstd.dylib
file /usr/local/lib/QtGui.framework/QtGui
qmake CONFIG+=no_extra_tiff_handler CONFIG+=release CONFIG+=zim_support QMAKE_APPLE_DEVICE_ARCHS="arm64" CONFIG+=no_epwing_support CONFIG+=no_ffmpeg_player #CONFIG+=no_qtmultimedia_player
make
# 打包
- name: package
run: |
macdeployqt ${targetName}.app -qmldir=. -verbose=1 -dmg
- name: Set outputs
id: vars
run: |
echo "::set-output name=sha_short::$(git rev-parse --short=8 HEAD)"
echo "::set-output name=release_date::$(date +'%Y%m%d')"
echo "::set-output name=release_time::$(date +'%H%M%S')"
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
# tag 上传Release
# - name: uploadRelease
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ${{ env.targetName }}.dmg
# asset_name: ${{ env.targetName }}-M1_${{ matrix.os }}_${{ matrix.qt_ver }}_${{ steps.vars.outputs.sha_short }}.dmg
# tag: v${{ steps.autotag.outputs.version }}-${{ steps.vars.outputs.sha_short }}
# overwrite: true
# release_name: win-ubuntu-macos-${{ github.ref_name }}-${{steps.vars.outputs.release_date}}
# prerelease: false
# body: |
# release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
# branch: ${{ github.ref_name }}
# commit: ${{ steps.vars.outputs.sha_short }}
# Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
# Windows built with: msvc64 Visual studio 2019
# goldendict.exe was provided alone ,if you have a previous version. replace this maybe ok. if not ,download the whole bundle.
# AppImage built with: Ubuntu-20.04 ,latest gcc
# macos built with: macos-10.15,macos-11.0,clang_64 x86_64(Intel Kind)
# This is a prerelease version ,auto build by github action. use on your on risk:-)

124
.github/workflows/macos.yml vendored Normal file
View file

@ -0,0 +1,124 @@
name: macos
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_run:
workflows: [AutoTag]
types: [completed]
workflow_dispatch:
# push:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
# - ".clang-format"
# pull_request:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-10.15,macos-11.0]
qt_ver: [5.15.2]
qt_arch: [clang_64]
env:
targetName: GoldenDict
version: 22.4.Summer
steps:
# macos 11.0 默认环境变了,要指定
- name: prepare env
if: ${{ matrix.os == 'macos-11.0' }}
run: |
softwareupdate --all --install --force
sudo xcode-select --print-path
sudo xcode-select --switch /Library/Developer/CommandLineTools
# brew install qt@6
- uses: actions/setup-python@v3
with:
python-version: '3.9'
- name: Install Qt
uses: jurplel/install-qt-action@v2
# if: ${{ matrix.qt_ver == '5.15.2' }}
with:
version: ${{ matrix.qt_ver }}
cached: 'false'
modules: qtwebengine
setup-python: 'false'
py7zrversion: '==0.18.1'
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: build macos
run: |
wget ftp://ftp.sra.co.jp/pub/misc/eb/eb-4.4.3.tar.bz2
tar xvjf eb-4.4.3.tar.bz2
cd eb-4.4.3 && ./configure && make -j 8 && sudo make install && cd ..
#brew install qt # or use official offline installer
brew install opencc libao hunspell ffmpeg@5 libtiff xz lzo libogg libvorbis zstd
qmake CONFIG+=release CONFIG+=zim_support CONFIG+=chinese_conversion_support
make
# 打包
- name: package
run: |
macdeployqt ${targetName}.app -qmldir=. -verbose=1 -dmg
otool -L GoldenDict.app/Contents/MacOS/GoldenDict
- name: Set outputs
id: vars
run: |
echo "::set-output name=sha_short::$(git rev-parse --short=8 HEAD)"
echo "::set-output name=release_date::$(date +'%Y%m%d')"
echo "::set-output name=release_time::$(date +'%H%M%S')"
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
echo "previousTag : $previousTag"
CHANGELOG="$(git log --oneline --no-decorate $previousTag..HEAD)"
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
# tag 上传Release
- name: uploadRelease
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.targetName }}.dmg
asset_name: ${{ matrix.qt_ver }}-${{ env.targetName }}_${{ matrix.os }}_${{ steps.vars.outputs.sha_short }}.dmg
tag: v${{env.version}}-${{ steps.vars.outputs.sha_short }}
overwrite: true
release_name: win-linux-macos-${{steps.vars.outputs.release_date}}
prerelease: false
body: |
release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
branch: ${{ github.ref_name }}
commit: ${{ steps.vars.outputs.sha_short }}
Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
Windows built with: msvc64 Visual studio 2019
## goldendict.exe can not used alone
if you have a previous version. replace this maybe ok. if not ,download the whole bundle.
AppImage built with: Ubuntu-20.04 ,latest gcc
macos built with: macos-10.15,macos-11.0,clang_64 x86_64(Intel Kind)
auto built by github action. use on your on risk:-)
CHANGES:
${{ steps.vars.outputs.COMMIT_SUMMARY }}

134
.github/workflows/ubuntu-6.2.yml vendored Normal file
View file

@ -0,0 +1,134 @@
name: Ubuntu-6.2
# Qt官方没有linux平台的x86包
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
# workflow_run:
# workflows: [AutoTag]
# types: [completed]
workflow_dispatch:
# push:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
# - ".clang-format"
# pull_request:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
qt_ver: [6.2.3]
qt_arch: [gcc_64]
env:
version: 22.4.Summer
steps:
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
cached: 'false'
modules: qtwebengine qtwebchannel qtpositioning qt5compat qtmultimedia
- name: ubuntu install thirdparty dependencies
run: |
sudo apt-get install git pkg-config build-essential
sudo apt-get install libvorbis-dev zlib1g-dev libhunspell-dev x11proto-record-dev
sudo apt-get install libxtst-dev liblzo2-dev libbz2-dev
sudo apt-get install libao-dev libavutil-dev libavformat-dev libtiff5-dev libeb16-dev
sudo apt-get install doxygen libzstd-dev libxkbcommon-dev libgstreamer-plugins-base1.0-0 libgstreamer-gl1.0-0
sudo ln -sf /usr/bin/x86_64-linux-gnu-ld.gold /usr/bin/ld
#build opencc
git clone https://github.com/BYVoid/OpenCC
cd OpenCC/
make PREFIX=/usr -j$(nproc)
sudo make install
cd ..
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: build goldendict
run: |
qmake CONFIG+=release PREFIX=/usr CONFIG+=zim_support CONFIG+=chinese_conversion_support
make INSTALL_ROOT=appdir -j`nproc` install; find appdir/
#copy missing shared dll to appdir.
mkdir -p appdir/usr/lib
# mkdir -p appdir/usr/libexec
cp $(ldd appdir/usr/bin/goldendict | grep -o '\W/[^ ]*' |grep gobject ) appdir/usr/lib
cp $(ldd appdir/usr/bin/goldendict | grep -o '\W/[^ ]*' |grep libpango ) appdir/usr/lib
# cp $${env.Qt6_DIR}/libexec/QtWebEngineProcess appdir/usr/libexec
- name: Build AppImage
run: |
wget -c -nv "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
chmod a+x linuxdeploy-plugin-qt-x86_64.AppImage
wget -c -nv "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
chmod a+x linuxdeploy-x86_64.AppImage
./linuxdeploy-x86_64.AppImage --appdir appdir --output appimage --plugin qt -i redist/icons/goldendict.png -d redist/org.goldendict.GoldenDict.desktop
# - uses: actions/upload-artifact@v2
# with:
# name: AppImage
# path: './*.AppImage*'
- name: Set outputs
id: vars
run: |
echo "::set-output name=sha_short::$(git rev-parse --short=8 HEAD)"
echo "::set-output name=release_date::$(date +'%Y%m%d')"
echo "::set-output name=release_time::$(date +'%H%M%S')"
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
echo "::set-output name=appname::$(ls *.AppImage*)"
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
echo "previousTag : $previousTag"
CHANGELOG="$(git log --oneline --no-decorate $previousTag..HEAD)"
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
- name: uploadRelease
# if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.vars.outputs.appname }}
asset_name: ${{ matrix.qt_ver }}-${{ steps.vars.outputs.appname }}
tag: v${{env.version}}-${{ steps.vars.outputs.sha_short }}
overwrite: true
release_name: win-linux-macos-${{steps.vars.outputs.release_date}}
prerelease: false
body: |
release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
branch: ${{ github.ref_name }}
commit: ${{ steps.vars.outputs.sha_short }}
Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
Windows built with: msvc64 Visual studio 2019
# goldendict.exe can not used alone
if you have a previous version. replace this maybe ok. if not ,download the whole bundle.
AppImage built with: Ubuntu-20.04 ,latest gcc
macos built with: macos-10.15,macos-11.0,clang_64 x86_64(Intel Kind)
auto built by github action. use on your on risk:-)
CHANGES:
${{ steps.vars.outputs.COMMIT_SUMMARY }}

View file

@ -1,19 +1,34 @@
name: Ubuntu
# Qt官方没有linux平台的x86包
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_run:
workflows: [AutoTag]
types: [completed]
workflow_dispatch:
push:
branches:
- dev
# paths:
# - '*.pro'
# - '.github/**'
pull_request:
branches:
- dev
# paths:
# - '*.pro'
# - '.github/**'
# push:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
# - ".clang-format"
# pull_request:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
jobs:
build:
name: Build
@ -23,9 +38,11 @@ jobs:
os: [ubuntu-20.04]
qt_ver: [5.15.2]
qt_arch: [gcc_64]
env:
version: 22.4.Summer
steps:
- name: Install Qt
uses: jurplel/install-qt-action@v2.13.0
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
cached: 'false'
@ -37,21 +54,28 @@ jobs:
sudo apt-get install qtdeclarative5-dev libxtst-dev liblzo2-dev libbz2-dev
sudo apt-get install libao-dev libavutil-dev libavformat-dev libtiff5-dev libeb16-dev
sudo apt-get install libqt5webkit5-dev libqt5svg5-dev libqt5x11extras5-dev qttools5-dev
sudo apt-get install qttools5-dev-tools qtmultimedia5-dev libqt5multimedia5-plugins libopencc-dev libzstd-dev
sudo apt-get install qttools5-dev-tools qtmultimedia5-dev libqt5multimedia5-plugins doxygen libzstd-dev #libopencc-dev
sudo ln -sf /usr/bin/x86_64-linux-gnu-ld.gold /usr/bin/ld
- uses: actions/checkout@v2
git clone https://github.com/BYVoid/OpenCC
pwd
cd OpenCC/
make PREFIX=/usr -j$(nproc)
sudo make install
cd ..
- uses: actions/checkout@v3
with:
fetch-depth: 1
# - name: build singleapplication
# run: |
# cd qtsingleapplication
# qmake
# make
fetch-depth: 0
- name: build goldendict
run: |
qmake CONFIG+=release PREFIX=/usr CONFIG+=zim_support CONFIG+=chinese_conversion_support
make INSTALL_ROOT=appdir -j`nproc` install; find appdir/
ls -al
#copy missing shared dll to appdir.
mkdir -p appdir/usr/lib
cp $(ldd appdir/usr/bin/goldendict | grep -o '\W/[^ ]*' |grep gobject ) appdir/usr/lib
cp $(ldd appdir/usr/bin/goldendict | grep -o '\W/[^ ]*' |grep libpango ) appdir/usr/lib
- name: Build AppImage
run: |
wget -c -nv "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
@ -59,35 +83,47 @@ jobs:
wget -c -nv "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
chmod a+x linuxdeploy-x86_64.AppImage
./linuxdeploy-x86_64.AppImage --appdir appdir --output appimage --plugin qt -i redist/icons/goldendict.png -d redist/org.goldendict.GoldenDict.desktop
- uses: actions/upload-artifact@v2
with:
name: AppImage
path: './*.AppImage*'
- name: Set outputs
id: vars
run: |
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
echo "::set-output name=sha_short::$(git rev-parse --short=8 HEAD)"
echo "::set-output name=release_date::$(date +'%Y%m%d')"
echo "::set-output name=release_time::$(date +'%H%M%S')"
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
echo "::set-output name=appname::$(ls *.AppImage*)"
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
echo "previousTag : $previousTag"
CHANGELOG="$(git log --oneline --no-decorate $previousTag..HEAD)"
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
- name: uploadRelease
# if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.vars.outputs.appname }}
asset_name: ${{ steps.vars.outputs.appname }}
tag: prerelease-${{steps.vars.outputs.release_date}}
asset_name: ${{ matrix.qt_ver }}-${{ steps.vars.outputs.appname }}
tag: v${{env.version}}-${{ steps.vars.outputs.sha_short }}
overwrite: true
release_name: Ubuntu-Windows-${{ github.ref_name }}.${{ steps.vars.outputs.sha_short }} built on ${{steps.vars.outputs.release_date}} ${{steps.vars.outputs.release_time_clock}}
prerelease: true
release_name: win-linux-macos-${{steps.vars.outputs.release_date}}
prerelease: false
body: |
release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
branch: ${{ github.ref_name }}
commit: ${{ steps.vars.outputs.sha_short }}
Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
Windows built with: msvc64 Visual studio 2019
AppImage built with: Ubuntu-20.04 ,latest gcc
## goldendict.exe can not used alone
if you have a previous version. replace this maybe ok. if not ,download the whole bundle.
This is a prerelease version ,auto build by github action. use on your on risk:-)
AppImage built with: Ubuntu-20.04 ,latest gcc
macos built with: macos-10.15,macos-11.0,clang_64 x86_64(Intel Kind)
auto built by github action. use on your on risk:-)
CHANGES:
${{ steps.vars.outputs.COMMIT_SUMMARY }}

170
.github/workflows/windows-6.2.yml vendored Normal file
View file

@ -0,0 +1,170 @@
name: Windows-6.2
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_run:
workflows: [AutoTag]
types: [completed]
workflow_dispatch:
# push代码时触发workflow
# push:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
# - ".clang-format"
# pull_request:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
jobs:
build:
name: Build
# 运行平台, windows-latest目前是windows server 2019
# 参考文档 https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md
runs-on: windows-2019
strategy:
# 矩阵配置
matrix:
# qt_ver: [5.15.2,6.2.2]
include:
# 5.15.2 参考 https://mirrors.cloud.tencent.com/qt/online/qtsdkrepository/windows_x86/desktop/qt5_5152/
# - qt_ver: 5.15.2
# qt_arch: win64_msvc2019_64
# msvc_arch: x64
# qt_target: x64
# qt_arch_install: msvc2019_64
- qt_ver: 6.2.3
qt_arch: win64_msvc2019_64
msvc_arch: x64
qt_target: x64
qt_arch_install: msvc2019_64
env:
targetName: GoldenDict.exe
version: 22.4.Summer
# 步骤
steps:
# 安装Qt
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
# Version of Qt to install
version: ${{ matrix.qt_ver }}
# Target platform for build
# target: ${{ matrix.qt_target }}
arch: ${{ matrix.qt_arch }}
cached: 'false'
modules: qtwebengine qtwebchannel qtpositioning qt5compat qtmultimedia
# 拉取代码
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set outputs
id: vars
shell: bash
run: |
echo "::set-output name=sha_short::$(git rev-parse --short=8 HEAD)"
echo "::set-output name=release_date::$(date +'%Y%m%d')"
echo "::set-output name=release_time::$(date +'%H%M%S')"
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
echo "previousTag : $previousTag"
CHANGELOG="$(git log --oneline --no-decorate $previousTag..HEAD)"
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
# # msvc编译
# - uses: ilammy/msvc-dev-cmd@v1
# with:
# arch: ${{ matrix.msvc_arch }}
- name: msvc-build goldendict
id: build
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.msvc_arch }}
qmake "CONFIG+=zim_support" CONFIG+=release
nmake
echo winSdkDir=%WindowsSdkDir% >> %GITHUB_ENV%
echo winSdkVer=%WindowsSdkVersion% >> %GITHUB_ENV%
echo vcToolsInstallDir=%VCToolsInstallDir% >> %GITHUB_ENV%
echo vcToolsRedistDir=%VCToolsRedistDir% >> %GITHUB_ENV%
echo QTDIR=%Qt6_DIR% >> %GITHUB_ENV%
# 打包
- name: package
id: package
env:
archiveName: GoldenDict-${{ github.ref_name }}.${{ steps.vars.outputs.sha_short }}-${{ steps.vars.outputs.release_time }}
msvcArch: ${{ matrix.msvc_arch }}
shell: pwsh
run: |
& .github\scripts\windows-publish.ps1 ${env:archiveName} ${env:targetName}
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
# tag 查询github-Release
# 上传artifacts
# - uses: actions/upload-artifact@v2
# with:
# name: ${{ steps.package.outputs.packageName }}
# path: ${{ steps.package.outputs.packageName }}.zip
# tag 上传Release
- name: uploadRelease
# if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ matrix.qt_ver }}-${{ steps.package.outputs.packageName }}.zip
tag: v${{env.version}}-${{ steps.vars.outputs.sha_short }}
overwrite: true
release_name: win-linux-macos-${{steps.vars.outputs.release_date}}
prerelease: false
body: |
release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
branch: ${{ github.ref_name }}
commit: ${{ steps.vars.outputs.sha_short }}
Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
Windows built with: msvc64 Visual studio 2019
AppImage built with: Ubuntu-20.04 ,latest gcc
auto built by github action. use on your on risk:-)
- name: upload goldendict.exe only
# if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: release/${{ env.targetName }}
asset_name: ${{ matrix.qt_ver }}-${{ env.targetName }}
tag: v${{env.version}}-${{ steps.vars.outputs.sha_short }}
overwrite: true
release_name: win-linux-macos-${{steps.vars.outputs.release_date}}
prerelease: false
body: |
release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
branch: ${{ github.ref_name }}
commit: ${{ steps.vars.outputs.sha_short }}
Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
Windows built with: msvc64 Visual studio 2019
goldendict.exe was provided alone ,if you have a previous version. replace this maybe ok. if not ,download the whole bundle.
AppImage built with: Ubuntu-20.04 ,latest gcc
macos built with: macos-10.15,macos-11.0,clang_64 x86_64(Intel Kind)
auto built by github action. use on your on risk:-)

View file

@ -1,19 +1,34 @@
name: Windows
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_run:
workflows: [AutoTag]
types: [completed]
workflow_dispatch:
# push代码时触发workflow
push:
branches:
- dev
# paths:
# - '*.pro'
# - '.github/**'
pull_request:
branches:
- dev
# paths:
# - '*.pro'
# - '.github/**'
# push:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
# - ".clang-format"
# pull_request:
# branches:
# - dev
# - master
# # - staged
# paths-ignore:
# - 'docs/**'
# - ".github/**"
# - "howto/**"
# - "*.md"
jobs:
build:
name: Build
@ -30,8 +45,14 @@ jobs:
msvc_arch: x64
qt_target: x64
qt_arch_install: msvc2019_64
# - qt_ver: 6.2.3
# qt_arch: win64_msvc2019_64
# msvc_arch: x64
# qt_target: x64
# qt_arch_install: msvc2019_64
env:
targetName: GoldenDict.exe
version: 22.4.Summer
# 步骤
steps:
# 安装Qt
@ -47,30 +68,42 @@ jobs:
cached: 'false'
modules: qtwebengine
# 拉取代码
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 1
fetch-depth: 0
- name: Set outputs
id: vars
shell: bash
run: |
echo "::set-output name=sha_short::$(git rev-parse --short=8 HEAD)"
echo "::set-output name=release_date::$(date +'%Y%m%d')"
echo "::set-output name=release_time::$(date +'%H%M%S')"
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
echo "previousTag : $previousTag"
CHANGELOG="$(git log --oneline --no-decorate $previousTag..HEAD)"
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
# msvc编译
- name: msvc-build goldendict
id: build
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.msvc_arch }}
qmake "CONFIG+=zim_support"
qmake "CONFIG+=zim_support" CONFIG+=release
nmake
echo winSdkDir=%WindowsSdkDir% >> %GITHUB_ENV%
echo winSdkVer=%WindowsSdkVersion% >> %GITHUB_ENV%
echo vcToolsInstallDir=%VCToolsInstallDir% >> %GITHUB_ENV%
echo vcToolsRedistDir=%VCToolsRedistDir% >> %GITHUB_ENV%
echo QTDIR=%Qt5_DIR% >> %GITHUB_ENV%
- name: Set outputs
id: vars
run: |
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
echo "::set-output name=release_date::$(date +'%Y%m%d')"
echo "::set-output name=release_time::$(date +'%H%M%S')"
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
# 打包
- name: package
id: package
@ -95,17 +128,45 @@ jobs:
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ steps.package.outputs.packageName }}.zip
tag: prerelease-${{steps.vars.outputs.release_date}}
asset_name: ${{ matrix.qt_ver }}-${{ steps.package.outputs.packageName }}.zip
tag: v${{env.version}}-${{ steps.vars.outputs.sha_short }}
overwrite: true
release_name: Ubuntu-Windows-${{ github.ref_name }}.${{ steps.vars.outputs.sha_short }} built on ${{steps.vars.outputs.release_date}} ${{steps.vars.outputs.release_time_clock}}
prerelease: true
release_name: win-linux-macos-${{steps.vars.outputs.release_date}}
prerelease: false
body: |
release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
branch: ${{ github.ref_name }}
commit: ${{ steps.vars.outputs.sha_short }}
Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
Windows built with: msvc64 Visual studio 2019
## goldendict.exe can not used alone
if you have a previous version. replace this maybe ok. if not ,download the whole bundle.
AppImage built with: Ubuntu-20.04 ,latest gcc
This is a prerelease version ,auto build by github action. use on your on risk:-)
auto built by github action. use on your on risk:-)
CHANGES:
${{ steps.vars.outputs.COMMIT_SUMMARY }}
- name: upload goldendict.exe only
# if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: release/${{ env.targetName }}
asset_name: ${{ matrix.qt_ver }}-${{ env.targetName }}
tag: v${{env.version}}-${{ steps.vars.outputs.sha_short }}
overwrite: true
release_name: win-linux-macos-${{steps.vars.outputs.release_date}}
prerelease: false
body: |
release on date: ${{steps.vars.outputs.release_date}} time: ${{steps.vars.outputs.release_time_clock}}
branch: ${{ github.ref_name }}
commit: ${{ steps.vars.outputs.sha_short }}
Qt version: ${{ matrix.qt_ver }} ${{ matrix.qt_arch }}
Windows built with: msvc64 Visual studio 2019
## goldendict.exe can not used alone
if you have a previous version. replace this maybe ok. if not ,download the whole bundle.
AppImage built with: Ubuntu-20.04 ,latest gcc
macos built with: macos-10.15,macos-11.0,clang_64 x86_64(Intel Kind)
auto built by github action. use on your on risk:-)

10
.gitignore vendored
View file

@ -1,16 +1,11 @@
*.o
*~
mouseover_win32/*.dll
mouseover_win32/*.a
locale/*.qm
debug/
build/
release/
tmp/
goldendict
winlibs/lib32-48/
Makefile
Makefile.Debug
@ -27,8 +22,6 @@ version.txt
.gitattributes
/goldendict.app/
/GoldenDict.app/
*.dmg
.DS_Store
@ -40,3 +33,6 @@ GoldenDict.xcodeproj/
*.opensdf
*.suo
*.vcxproj.user
/.idea
/.vs
/.vscode

View file

@ -1,9 +1,31 @@
# all the changes:
# Changes
## Until to now
- **CLEANING OLD/USELESS CODE**
- mac m1 Sillion chip support from [@ngn999](https://github.com/ngn999)
## Until to 2022-3-24
- upgrade opencc to 2020-04-26 version(through vcpkg)
- upgrade ffmpeg dependency to 4.4(on windows),code support to 5.0
- fix: double click word to translate ,right context menu does not display.
- add macos release workflow ,though not verified.
- fix:middle button open in new tab does not work.
- optimize: large memory consumption ,when have large collection of dictionaries.even when query a small group of dictionaries.
- peformance: dsl parse performance .
when have very long lines,the line will be split into two parts .the remaining part was considered a normal headword ,and hanged when expand parts.
- support qt6.2.3
- performance improve when edit dictionary groups.
## Until to 2022-2-2
- replace webkit with webenginewidgets
- clean old code.
- remove old `if 0` code section
- qt_version check
- remove IS_QT_5 check
rename qt4x5.hh to utils.hh,for the name is not proper now.
- QString::SkipEmptyParts=>Qt::SkipEmptyParts
- remove "CONFIG+=old_hunspell"

View file

@ -1,14 +0,0 @@
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>

View file

@ -1,4 +1,6 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/e507f9bf83bd48f7a5b76f71dfe9f0dd)](https://app.codacy.com/gh/xiaoyifang/goldendict?utm_source=github.com&utm_medium=referral&utm_content=xiaoyifang/goldendict&utm_campaign=Badge_Grade_Settings)
[![Windows](https://github.com/xiaoyifang/goldendict/actions/workflows/windows.yml/badge.svg)](https://github.com/xiaoyifang/goldendict/actions/workflows/windows.yml) [![Ubuntu](https://github.com/xiaoyifang/goldendict/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/xiaoyifang/goldendict/actions/workflows/ubuntu.yml)
[![macos](https://github.com/xiaoyifang/goldendict/actions/workflows/macos.yml/badge.svg)](https://github.com/xiaoyifang/goldendict/actions/workflows/macos.yml)
## Introduction
@ -6,7 +8,7 @@
## Requirements
This code has been run and tested on Windows XP/Vista/7, Ubuntu Linux, Mac OS X.
This code has been run and tested on Windows 10/11, Ubuntu Linux, Mac OS X.
### External Deps
@ -23,24 +25,36 @@ This code has been run and tested on Windows XP/Vista/7, Ubuntu Linux, Mac OS X.
libvorbis-dev zlib1g-dev libhunspell-dev x11proto-record-dev \
qtdeclarative5-dev libxtst-dev liblzo2-dev libbz2-dev \
libao-dev libavutil-dev libavformat-dev libtiff5-dev libeb16-dev \
libqt5webkit5-dev libqt5svg5-dev libqt5x11extras5-dev qttools5-dev \
libqt5svg5-dev libqt5x11extras5-dev qttools5-dev \
qttools5-dev-tools qtmultimedia5-dev libqt5multimedia5-plugins
## How to build
First, clone this repository, e.g.:
git clone git://github.com/goldendict/goldendict.git
git clone https://github.com/goldendict/goldendict.git
### Linux
And then invoke `qmake-qt5` and `make`:
cd goldendict && qmake-qt5 && make
make sure that `qmake` is from Qt 5 installation. If not, you can try
finding it at a path like `/usr/lib/x86_64-linux-gnu/qt5/bin/qmake`.
### macOS
```
wget ftp://ftp.sra.co.jp/pub/misc/eb/eb-4.4.3.tar.bz2
tar xvjf eb-4.4.3.tar.bz2
cd eb-4.4.3 && ./configure && make -j 8 && sudo make install
brew install qt # or use official offline installer
brew install opencc libao hunspell ffmpeg libtiff xz lzo libogg libvorbis
qmake CONFIG+=release CONFIG+=zim_support CONFIG+=chinese_conversion_support
make
make install
```
### Windows
Alternatively, you might want to load `goldendict.pro` file from within Qt Creator, especially on Windows.
Note: `libhunspell` version > 1.5.
### Building with Chinese conversion support
@ -100,9 +114,7 @@ Then, invoke `make clean` before `make` because the setting change:
### Building under Windows with MS Visual Studio
To build GoldenDict with Visual Studio take one of next library packs and unpack it to `"winlibs/lib/msvc"` folder in GoldenDict sources folder.
[GoldenDict_libs_VS2015_x86_v4.7z](http://www.mediafire.com/file/0a7ygy9rn99oevm/GoldenDict_libs_VS2015_x86_v4.7z) - for MS Visual Studio 2015, 32 bit
[GoldenDict_libs_VS2015_x64_v4.7z](http://www.mediafire.com/file/yoy2q8af0s1467m/GoldenDict_libs_VS2015_x64_v4.7z) - for MS Visual Studio 2015, 64 bit
the source code has offered precompile x64 windows libs on winlibs/lib/msvc. you can build your own version either.
To build with Visual Studio.
check this [how to build with visual studio](howto/how%20to%20build%20and%20debug%20with%20VS2019.md)

View file

@ -261,7 +261,7 @@ class AardDictionary: public BtreeIndexing::BtreeDictionary
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception );
;
virtual QString const& getDescription();
@ -826,7 +826,7 @@ sptr< Dictionary::DataRequest > AardDictionary::getArticle( wstring const & word
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception )
{
return new AardArticleRequest( word, alts, *this, ignoreDiacritics );
}
@ -838,7 +838,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
string const & indicesDir,
Dictionary::Initializing & initializing,
unsigned maxHeadwordsToExpand )
THROW_SPEC( std::exception )
{
vector< sptr< Dictionary::Class > > dictionaries;
@ -940,8 +940,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
quint16 volumes = qFromBigEndian( dictHeader.totalVolumes );
if( volumes > 1 )
{
QString ss;
ss.sprintf( " (%i/%i)", qFromBigEndian( dictHeader.volume ), volumes );
QString ss=QString( " (%1/%2)").arg( qFromBigEndian( dictHeader.volume ), volumes );
dictName += ss.toLocal8Bit().data();
}

View file

@ -17,7 +17,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
string const & indicesDir,
Dictionary::Initializing &,
unsigned maxHeadwordsToExpand )
THROW_SPEC( std::exception );
;
}

View file

@ -134,6 +134,12 @@ a:hover {
display: none;
}
/* Headers */
h3 {
color: inherit;
font-family: Arial;
}
/* The first headword in a (possibly) multi-headword DSL article */
.gdarticlebody > div:first-child .dsl_headwords,
.gdarticlebody > h3:first-child {
@ -162,12 +168,6 @@ code::selection {
background: #839EC7;
}
/* Headers */
h3 {
color: inherit;
font-family: Arial;
}
/******** DSL Dictionaries ****************/
/* DSL headwords */
@ -226,9 +226,6 @@ h3 {
-webkit-border-radius: 100px;
text-align: center;
vertical-align: text-bottom;
}
.dsl_s_wav a {
color: #FFF;
border: 1px solid #798415;
-webkit-box-shadow: 1px 1px #CCC, inset -1px -1px #4E7500;

View file

@ -129,7 +129,7 @@ pre.sdct_m
}
/* StarDict type 'l' -- Pure meaning which used to be in locale encoding. */
pre.sdct_m
pre.sdct_l
{
}
@ -791,6 +791,8 @@ div.xdxf
font-style: italic;
}
.mwiki td.mw-label { vertical-align: top; }
.mwiki td.mw-submit { white-space: nowrap; }
/**
* Forms
*/
@ -801,9 +803,6 @@ div.xdxf
.mwiki body.rtl td.mw-input { text-align: right; }
.mwiki body.rtl td.mw-submit { text-align: right; }
.mwiki td.mw-label { vertical-align: top; }
.mwiki td.mw-submit { white-space: nowrap; }
/**
* Image captions
*/
@ -2887,7 +2886,7 @@ in bg url to hide it from iemac */
/****** Wiktionary-specific excerpts *********/
.mwiki .audiolink a {
background: url("http://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Loudspeaker.svg/16px-Loudspeaker.svg.png") center left no-repeat !important;
background: url("https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Loudspeaker.svg/16px-Loudspeaker.svg.png") center left no-repeat !important;
padding-left: 20px !important;
padding-right: 0 !important;
}

37
article_inspect.cpp Normal file
View file

@ -0,0 +1,37 @@
#include "article_inspect.h"
#include <QCloseEvent>
#if (QT_VERSION > QT_VERSION_CHECK(6,0,0))
#include <QWebEngineContextMenuRequest>
#endif
ArticleInspector::ArticleInspector( QWidget * parent ) : QDialog( parent, Qt::WindowType::Window )
{
setAttribute( Qt::WidgetAttribute::WA_DeleteOnClose, false );
QVBoxLayout * v = new QVBoxLayout( this );
v->setSpacing( 0 );
v->setContentsMargins( 0, 0, 0, 0 );
inspectView = new QWebEngineView();
v->addWidget( inspectView );
}
void ArticleInspector::setInspectPage( QWebEngineView * view )
{
auto page=view->page();
this->inspectedPage = page;
page->setDevToolsPage( inspectView->page() );
#if( QT_VERSION > QT_VERSION_CHECK( 6, 0, 0 ) )
// without this line, application will crash on qt6.2 ,see https://bugreports.qt.io/browse/QTBUG-101724
if( view->lastContextMenuRequest() )
{
page->triggerAction( QWebEnginePage::InspectElement );
}
#else
page->triggerAction( QWebEnginePage::InspectElement );
#endif
raise();
show();
}
void ArticleInspector::closeEvent( QCloseEvent * )
{
inspectedPage->setDevToolsPage( nullptr );
}

24
article_inspect.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef ARTICLE_INSPECT_H
#define ARTICLE_INSPECT_H
#include <QDialog>
#include <QWebEngineView>
#include <QWebEnginePage>
#include <QVBoxLayout>
class ArticleInspector : public QDialog
{
Q_OBJECT
QWebEngineView * inspectView = nullptr;
QWebEnginePage * inspectedPage = nullptr;
public:
ArticleInspector( QWidget * parent = nullptr );
void setInspectPage( QWebEngineView * view);
private:
virtual void closeEvent( QCloseEvent * );
};
#endif // ARTICLE_INSPECT_H

View file

@ -56,7 +56,7 @@ std::string ArticleMaker::makeHtmlHeader( QString const & word,
result += "<script type=\"text/javascript\" "
"src=\"qrc:///resources/jquery-3.6.0.slim.min.js\"></script>";
result += "<script> var $_$=$.noConflict(true); </script>";
result += "<script> var $_$=$.noConflict(); </script>";
//custom javascript
result += "<script type=\"text/javascript\" src=\"qrc:///resources/gd-custom.js\"></script>";
@ -126,7 +126,7 @@ std::string ArticleMaker::makeHtmlHeader( QString const & word,
}
}
result += "<title>" + Html::escape( Utf8::encode( gd::toWString( word ) ) ) + "</title>";
result += "<title>" + Html::escape( word.toStdString()) + "</title>";
// This doesn't seem to be much of influence right now, but we'll keep
// it anyway.

View file

@ -1,14 +1,8 @@
/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#if defined( _MSC_VER ) && _MSC_VER < 1800 // VS2012 and older
#include <stdint_msvc.h>
#else
#include <stdint.h>
#endif
#include <QUrl>
#include "article_netmgr.hh"
#include "wstring_qt.hh"
#include "gddebug.hh"
@ -32,7 +26,7 @@ using std::string;
connect( baseReply, SIGNAL( metaDataChanged() ), this, SLOT( applyMetaData() ) );
connect( baseReply, SIGNAL( error( QNetworkReply::NetworkError) ),
connect( baseReply, SIGNAL( errorOccurred( QNetworkReply::NetworkError) ),
this, SLOT( applyError( QNetworkReply::NetworkError ) ) );
connect( baseReply, SIGNAL( readyRead() ), this, SLOT( readDataFromBase() ) );
@ -113,8 +107,8 @@ using std::string;
baseReply->attribute( QNetworkRequest::HttpPipeliningWasUsedAttribute ) );
setAttribute( QNetworkRequest::BackgroundRequestAttribute,
baseReply->attribute( QNetworkRequest::BackgroundRequestAttribute ) );
setAttribute( QNetworkRequest::SpdyWasUsedAttribute,
baseReply->attribute( QNetworkRequest::SpdyWasUsedAttribute ) );
setAttribute( QNetworkRequest::Http2WasUsedAttribute,
baseReply->attribute( QNetworkRequest::Http2WasUsedAttribute ) );
emit metaDataChanged();
}
@ -133,7 +127,7 @@ using std::string;
void AllowFrameReply::applyError( QNetworkReply::NetworkError code )
{
setError( code, baseReply->errorString() );
emit error( code );
emit errorOccurred( code );
}
void AllowFrameReply::readDataFromBase()
@ -283,7 +277,7 @@ QNetworkReply * ArticleNetworkAccessManager::createRequest( Operation op,
QNetworkRequest newReq(req);
if ( hideGoldenDictHeader && req.url().scheme().startsWith("http", Qt::CaseInsensitive))
{
newReq.setRawHeader("User-Agent", req.rawHeader("User-Agent").replace(qApp->applicationName(), ""));
newReq.setRawHeader("User-Agent", req.rawHeader("User-Agent").replace(qApp->applicationName().toUtf8(), ""));
}
QNetworkReply * reply = QNetworkAccessManager::createRequest( op, newReq, outgoingData );
@ -336,8 +330,8 @@ sptr< Dictionary::DataRequest > ArticleNetworkAccessManager::getResource(
// See if we have some dictionaries muted
QSet< QString > mutedDicts =
QSet< QString >::fromList( Utils::Url::queryItemValue( url, "muted" ).split( ',' ) );
QStringList mutedDictLists=Utils::Url::queryItemValue( url, "muted" ).split( ',' );
QSet< QString > mutedDicts ( mutedDictLists.begin(),mutedDictLists.end());
// Unpack contexts
@ -525,7 +519,7 @@ void ArticleResourceReply::readyReadSlot()
void ArticleResourceReply::finishedSlot()
{
if (req->dataSize() < 0) {
emit error(ContentNotFoundError);
emit errorOccurred(ContentNotFoundError);
setError(ContentNotFoundError, "content not found");
}
@ -569,5 +563,6 @@ void LocalSchemeHandler::requestStarted(QWebEngineUrlRequestJob *requestJob)
connect(reply,&QNetworkReply::finished,requestJob,[=](){
requestJob->reply("text/html",reply);
});
connect(requestJob, &QObject::destroyed, reply, &QObject::deleteLater);
}

View file

@ -2,6 +2,7 @@
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "articleview.hh"
#include "QtCore/qvariant.h"
#include "folding.hh"
#include "fulltextsearch.hh"
#include "gddebug.hh"
@ -28,7 +29,14 @@
#include <QWebEngineSettings>
#include <assert.h>
#include <map>
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0) && QT_VERSION < QT_VERSION_CHECK(6,0,0))
#include <QWebEngineContextMenuData>
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QRegExp>
#include <QWebEngineContextMenuRequest>
#include <QWebEngineFindTextResult>
#endif
#ifdef Q_OS_WIN32
#include <windows.h>
#include <QPainter>
@ -172,27 +180,6 @@ public:
void ArticleView::emitJavascriptFinished(){
emit notifyJavascriptFinished();
}
//in webengine,javascript has been executed in async mode ,for simpility,use EventLoop to simulate sync execution.
//a better solution would be to replace it with callback etc.
QString ArticleView::runJavaScriptSync(QWebEnginePage* frame, const QString& variable)
{
qDebug("%s", QString("runJavascriptScriptSync:%1").arg(variable).toLatin1().data());
QString result;
QSharedPointer<QEventLoop> loop = QSharedPointer<QEventLoop>(new QEventLoop());
QTimer::singleShot(1000, loop.data(), &QEventLoop::quit);
frame->runJavaScript(variable, [=,&result](const QVariant &v)
{
if(loop->isRunning()){
if(v.isValid())
result = v.toString();
loop->quit();
}
});
loop->exec();
return result;
}
namespace {
@ -218,13 +205,10 @@ QString ArticleView::scrollToFromDictionaryId( QString const & dictionaryId )
return scrollToPrefix + dictionaryId;
}
ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm,
AudioPlayerPtr const & audioPlayer_,
ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm, AudioPlayerPtr const & audioPlayer_,
std::vector< sptr< Dictionary::Class > > const & allDictionaries_,
Instances::Groups const & groups_, bool popupView_,
Config::Class const & cfg_,
QAction & openSearchAction_,
QAction * dictionaryBarToggled_,
Instances::Groups const & groups_, bool popupView_, Config::Class const & cfg_,
QAction & openSearchAction_, QAction * dictionaryBarToggled_,
GroupComboBox const * groupComboBox_ ) :
QFrame( parent ),
articleNetMgr( nm ),
@ -324,24 +308,28 @@ ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm,
inspectAction.setText( tr( "Inspect" ) );
ui.definition->addAction( &inspectAction );
QWebEnginePage *page = ui.definition->page();
connect(&inspectAction, &QAction::triggered, this, [page, this]() {
if (inspectView == nullptr || !inspectView->isVisible()) {
inspectView = new QWebEngineView();
page->setDevToolsPage(inspectView->page());
page->triggerAction(QWebEnginePage::InspectElement);
inspectView->show();
}
});
connect(&inspectAction, &QAction::triggered, this, &ArticleView::inspectElement);
ui.definition->installEventFilter( this );
ui.searchFrame->installEventFilter( this );
ui.ftsSearchFrame->installEventFilter( this );
QWebEngineSettings * settings = ui.definition->page()->settings();
QWebEngineSettings * settings = ui.definition->settings();
settings->setUnknownUrlSchemePolicy(QWebEngineSettings::UnknownUrlSchemePolicy::DisallowUnknownUrlSchemes);
#if( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
settings->defaultSettings()->setAttribute( QWebEngineSettings::WebAttribute::LocalContentCanAccessRemoteUrls, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::WebAttribute::LocalContentCanAccessFileUrls, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::WebAttribute::ErrorPageEnabled, false);
settings->defaultSettings()->setAttribute(QWebEngineSettings::PluginsEnabled, cfg.preferences.enableWebPlugins);
settings->defaultSettings()->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, false);
#else
settings->setAttribute( QWebEngineSettings::WebAttribute::LocalContentCanAccessRemoteUrls, true );
settings->setAttribute( QWebEngineSettings::WebAttribute::LocalContentCanAccessFileUrls, true );
settings->setAttribute( QWebEngineSettings::WebAttribute::ErrorPageEnabled, false );
settings->setAttribute( QWebEngineSettings::PluginsEnabled, cfg.preferences.enableWebPlugins );
settings->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, false );
#endif
// Load the default blank page instantly, so there would be no flicker.
QString contentType;
@ -395,7 +383,7 @@ void ArticleView::showDefinition( Config::InputPhrase const & phrase, unsigned g
QString const & scrollTo,
Contexts const & contexts_ )
{
currentWord = phrase.phrase;
currentWord = phrase.phrase.trimmed();
currentActiveDictIds.clear();
// first, let's stop the player
audioPlayer->stop();
@ -473,7 +461,7 @@ void ArticleView::showDefinition( QString const & word, QStringList const & dict
{
if( dictIDs.isEmpty() )
return;
currentWord = word;
currentWord = word.trimmed();
// first, let's stop the player
audioPlayer->stop();
@ -515,47 +503,31 @@ void ArticleView::showAnticipation()
ui.definition->setCursor( Qt::WaitCursor );
}
void ArticleView::inspectElement(){
if( inspector == nullptr )
{
inspector = new ArticleInspector( this );
inspector->setWindowTitle( tr( "Inspect" ) );
}
inspector->setInspectPage( ui.definition );
}
void ArticleView::loadFinished( bool result )
{
setZoomFactor(cfg.preferences.zoomFactor);
QUrl url = ui.definition->url();
qDebug() << "article view loaded url:" << url.url ().left (200);
QVariant userDataVariant = ui.definition->property("currentArticle");
if ( userDataVariant.isValid() )
{
double sx = 0, sy = 0;
QVariant qsx=ui.definition->property("sx");
if ( qsx.type() == QVariant::Double )
sx = qsx.toDouble();
QVariant qsy = ui.definition->property("sx");
if ( qsy.type() == QVariant::Double )
sy = qsy.toDouble();
if ( sx != 0 || sy != 0 )
{
// Restore scroll position
ui.definition->page()->runJavaScript(
QString( "window.scroll( %1, %2 );" ).arg( sx ).arg( sy ) );
}
}
else
if( cfg.preferences.autoScrollToTargetArticle )
{
QString const scrollTo = Utils::Url::queryItemValue( url, "scrollto" );
if( isScrollTo( scrollTo ) )
{
// There is no active article saved in history, but we have it as a parameter.
// setCurrentArticle will save it and scroll there.
setCurrentArticle( scrollTo, true );
}
}
ui.definition->unsetCursor();
//QApplication::restoreOverrideCursor();
// Expand collapsed article if only one loaded
ui.definition->page()->runJavaScript( QString( "gdCheckArticlesNumber();" ) );
@ -690,11 +662,15 @@ void ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
return; // No action on background page, scrollIntoView there don't work
if(moveToIt){
QString script=QString(" var elem=document.getElementById('%1'); if(elem!=undefined){elem.scrollIntoView(true);}").arg(id);
QString dictId = id.mid( 7 );
if( dictId.isEmpty() )
return;
QString script = QString( "var elem=document.getElementById('%1'); "
"if(elem!=undefined){elem.scrollIntoView(true);} gdMakeArticleActive('%2',true);" )
.arg( id, dictId );
onJsActiveArticleChanged( id );
ui.definition->page()->runJavaScript( script );
ui.definition->setProperty("currentArticle",id);
setActiveArticleId(id.mid(7));
setActiveArticleId( dictId );
}
}
@ -704,13 +680,13 @@ void ArticleView::selectCurrentArticle()
QString( "gdSelectArticle( '%1' );var elem=document.getElementById('%2'); if(elem!=undefined){elem.scrollIntoView(true);}" ).arg( getActiveArticleId() ,getCurrentArticle()) );
}
bool ArticleView::isFramedArticle( QString const & ca )
void ArticleView::isFramedArticle( QString const & ca, const std::function< void( bool ) > & callback )
{
if( ca.isEmpty() )
return false;
callback( false );
QString result=runJavaScriptSync( ui.definition->page(), QString( "!!document.getElementById('gdexpandframe-%1');" ).arg( ca.mid( 7 ) ) );
return result=="true";
ui.definition->page()->runJavaScript( QString( "!!document.getElementById('gdexpandframe-%1');" ).arg( ca.mid( 7 ) ),
[ callback ]( const QVariant & res ) { callback( res.toBool() ); } );
}
bool ArticleView::isExternalLink( QUrl const & url )
@ -722,14 +698,15 @@ void ArticleView::tryMangleWebsiteClickedUrl( QUrl & url, Contexts & contexts )
{
// Don't try mangling audio urls, even if they are from the framed websites
if( ( url.scheme() == "http" || url.scheme() == "https" )
&& ! Dictionary::WebMultimediaDownload::isAudioUrl( url ) )
if( ( url.scheme() == "http" || url.scheme() == "https" ) && !Dictionary::WebMultimediaDownload::isAudioUrl( url ) )
{
// Maybe a link inside a website was clicked?
QString ca = getCurrentArticle();
if ( isFramedArticle( ca ) )
isFramedArticle( ca,
[ &url, &contexts, &ca ]( bool framed )
{
if( framed )
{
// QVariant result = runJavaScriptSync( ui.definition->page(), "gdLastUrlText" );
QVariant result;
@ -755,6 +732,7 @@ void ArticleView::tryMangleWebsiteClickedUrl( QUrl & url, Contexts & contexts )
url = target;
}
}
} );
}
}
@ -833,6 +811,17 @@ bool ArticleView::handleF3( QObject * /*obj*/, QEvent * ev )
bool ArticleView::eventFilter( QObject * obj, QEvent * ev )
{
#ifdef Q_OS_MAC
if( ev->type() == QEvent::NativeGesture )
{
qDebug() << "it's a Native Gesture!";
// handle Qt::ZoomNativeGesture Qt::SmartZoomNativeGesture here
// ignore swipe left/right.
// QWebEngine can handle Qt::SmartZoomNativeGesture.
}
#else
if( ev->type() == QEvent::Gesture )
{
Gestures::GestureResult result;
@ -859,15 +848,17 @@ bool ArticleView::eventFilter( QObject * obj, QEvent * ev )
int delta = result == Gestures::SWIPE_UP ? -120 : 120;
QWidget *widget = static_cast< QWidget * >( obj );
QPoint angleDelta(0, delta);
QPoint pixelDetal;
QWidget *child = widget->childAt( widget->mapFromGlobal( pt ) );
if( child )
{
QWheelEvent whev( child->mapFromGlobal( pt ), pt, delta, Qt::NoButton, Qt::NoModifier );
QWheelEvent whev( child->mapFromGlobal( pt ), pt, pixelDetal,angleDelta, Qt::NoButton, Qt::NoModifier,Qt::NoScrollPhase,false);
qApp->sendEvent( child, &whev );
}
else
{
QWheelEvent whev( widget->mapFromGlobal( pt ), pt, delta, Qt::NoButton, Qt::NoModifier );
QWheelEvent whev( widget->mapFromGlobal( pt ), pt,pixelDetal, angleDelta,Qt::NoButton, Qt::NoModifier,Qt::NoScrollPhase,false );
qApp->sendEvent( widget, &whev );
}
}
@ -875,6 +866,7 @@ bool ArticleView::eventFilter( QObject * obj, QEvent * ev )
return handled;
}
#endif
if( ev->type() == QEvent::MouseMove )
{
@ -925,6 +917,21 @@ bool ArticleView::eventFilter( QObject * obj, QEvent * ev )
return true;
}
}
else if( ev->type() == QEvent::Wheel )
{
QWheelEvent * pe = static_cast< QWheelEvent * >( ev );
if( pe->modifiers().testFlag( Qt::ControlModifier ) )
{
if( pe->angleDelta().y() > 0 )
{
zoomIn();
}
else
{
zoomOut();
}
}
}
}
else
return QFrame::eventFilter( obj, ev );
@ -1105,6 +1112,7 @@ void ArticleView::linkClicked( QUrl const & url_ )
( kmod & ( Qt::ControlModifier | Qt::ShiftModifier ) ) ) )
{
// Mid button or Control/Shift is currently pressed - open the link in new tab
ui.definition->resetMidButtonPressed();
emit openLinkInNewTab( url, ui.definition->url(), getCurrentArticle(), contexts );
}
else
@ -1114,6 +1122,10 @@ void ArticleView::linkClicked( QUrl const & url_ )
void ArticleView::linkClickedInHtml( QUrl const & url_ )
{
emit ui.definition->linkClickedInHtml(url_);
if(!url_.isEmpty())
{
linkClicked( url_ );
}
}
void ArticleView::openLink( QUrl const & url, QUrl const & ref,
QString const & scrollTo,
@ -1626,12 +1638,16 @@ void ArticleView::forward()
ui.definition->forward();
}
bool ArticleView::hasSound()
void ArticleView::hasSound( const std::function< void( bool ) > & callback )
{
QVariant v = runJavaScriptSync( ui.definition->page(),"gdAudioLinks.first" );
ui.definition->page()->runJavaScript( "gdAudioLinks.first",
[ callback ]( const QVariant & v )
{
bool has = false;
if( v.type() == QVariant::String )
return !v.toString().isEmpty();
return false;
has = !v.toString().isEmpty();
callback( has );
} );
}
//use webengine javascript to playsound
@ -1643,27 +1659,24 @@ void ArticleView::playSound()
" } "
" return link;})(); ";
QString soundScript = runJavaScriptSync(ui.definition->page(), variable);
// ui.definition->page()->runJavaScript(variable);
ui.definition->page()->runJavaScript(variable,[this](const QVariant & result){
if (result.type() == QVariant::String) {
QString soundScript = result.toString();
if (!soundScript.isEmpty())
openLink(QUrl::fromEncoded(soundScript.toUtf8()), ui.definition->url());
}
});
}
// use eventloop to turn the async callback to sync execution.
QString ArticleView::toHtml()
void ArticleView::toHtml( const std::function< void( QString & ) > & callback )
{
QString result;
QSharedPointer<QEventLoop> loop = QSharedPointer<QEventLoop>(new QEventLoop());
QTimer::singleShot(1000, loop.data(), &QEventLoop::quit);
ui.definition->page()->toHtml([loop, &result](const QString &content) {
if (loop->isRunning()) {
result = content;
loop->quit();
}
ui.definition->page()->toHtml(
[ = ]( const QString & content )
{
QString html = content;
callback( html );
} );
loop->exec();
return result;
}
void ArticleView::setHtml(const QString& content,const QUrl& baseUrl){
@ -1688,13 +1701,22 @@ Config::InputPhrase ArticleView::getPhrase() const
void ArticleView::print( QPrinter * printer ) const
{
//ui.definition->page()->print(printer, [](bool result) {});
QEventLoop loop;
bool result;
auto printPreview = [&](bool success) { result = success; loop.quit(); };
auto printPreview = [ & ]( bool success )
{
result = success;
loop.quit();
};
#if( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
ui.definition->page()->print( printer, std::move( printPreview ) );
#else
connect( ui.definition, &QWebEngineView::printFinished, &loop, std::move( printPreview ) );
ui.definition->print( printer );
#endif
loop.exec();
if (!result) {
if( !result )
{
qDebug() << "print failed";
}
}
@ -1722,8 +1744,12 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
QAction * saveImageAction = 0;
QAction * saveSoundAction = 0;
QWebEngineContextMenuData menuData=r->contextMenuData();
QUrl targetUrl(menuData.linkUrl());
#if( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
const QWebEngineContextMenuData * menuData = &(r->contextMenuData());
#else
QWebEngineContextMenuRequest * menuData = ui.definition->lastContextMenuRequest();
#endif
QUrl targetUrl(menuData->linkUrl());
Contexts contexts;
tryMangleWebsiteClickedUrl( targetUrl, contexts );
@ -1752,9 +1778,13 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
}
QUrl imageUrl;
if( !popupView && menuData.mediaType ()==QWebEngineContextMenuData::MediaTypeImage)
#if( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
if( !popupView && menuData->mediaType ()==QWebEngineContextMenuData::MediaTypeImage)
#else
if( !popupView && menuData->mediaType ()==QWebEngineContextMenuRequest::MediaType::MediaTypeImage)
#endif
{
imageUrl = menuData.mediaUrl ();
imageUrl = menuData->mediaUrl ();
if( !imageUrl.isEmpty() )
{
menu.addAction( ui.definition->pageAction( QWebEnginePage::CopyImageToClipboard ) );
@ -2012,7 +2042,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
}
}
qDebug( "title = %s\n", r->title().toLocal8Bit().data() );
qDebug()<< "title = "<< r->title();
}
@ -2142,12 +2172,15 @@ void ArticleView::moveOneArticleUp()
void ArticleView::moveOneArticleDown()
{
QString current = getCurrentArticle();
if ( current.size() )
{
QString currentDictId = dictionaryIdFromScrollTo( current );
QStringList lst = getArticlesList();
// if current article is empty .use the first as default.
if( currentDictId.isEmpty() && !lst.isEmpty() )
{
currentDictId = lst[ 0 ];
}
int idx = lst.indexOf( dictionaryIdFromScrollTo( current ) );
int idx = lst.indexOf( currentDictId );
if( idx != -1 )
{
@ -2156,7 +2189,6 @@ void ArticleView::moveOneArticleDown()
setCurrentArticle( scrollToFromDictionaryId( lst[ idx ] ), true );
}
}
}
void ArticleView::openSearch()
{
@ -2235,17 +2267,19 @@ void ArticleView::onJsActiveArticleChanged(QString const & id)
if ( !isScrollTo( id ) )
return; // Incorrect id
emit activeArticleChanged( this, dictionaryIdFromScrollTo( id ) );
QString dictId = dictionaryIdFromScrollTo( id );
setActiveArticleId( dictId );
emit activeArticleChanged( this, dictId );
}
void ArticleView::doubleClicked( QPoint pos )
{
// We might want to initiate translation of the selected word
audioPlayer->stop();
if ( cfg.preferences.doubleClickTranslates )
{
QString selectedText = ui.definition->selectedText();
emit sendWordToInputLine( selectedText );
// Do some checks to make sure there's a sensible selection indeed
if ( Folding::applyWhitespaceOnly( gd::toWString( selectedText ) ).size() &&
selectedText.size() < 60 )
@ -2330,12 +2364,22 @@ bool ArticleView::findText(QString& text, const QWebEnginePage::FindFlags& f)
// turn async to sync invoke.
QSharedPointer<QEventLoop> loop = QSharedPointer<QEventLoop>(new QEventLoop());
QTimer::singleShot(1000, loop.data(), &QEventLoop::quit);
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
ui.definition->findText(text, f, [&](const QWebEngineFindTextResult& result)
{
if(loop->isRunning()){
r = result.numberOfMatches()>0;
loop->quit();
} });
#else
ui.definition->findText(text, f, [&](bool result)
{
if(loop->isRunning()){
r = result;
loop->quit();
} });
#endif
loop->exec();
return r;
@ -2459,10 +2503,9 @@ void ArticleView::highlightFTSResults()
else
regexp.setPattern( regString );
QRegularExpression::PatternOptions patternOptions = QRegularExpression::DotMatchesEverythingOption
| QRegularExpression::UseUnicodePropertiesOption
| QRegularExpression::MultilineOption
| QRegularExpression::InvertedGreedinessOption;
QRegularExpression::PatternOptions patternOptions =
QRegularExpression::DotMatchesEverythingOption | QRegularExpression::UseUnicodePropertiesOption |
QRegularExpression::MultilineOption | QRegularExpression::InvertedGreedinessOption;
if( !Utils::Url::hasQueryItem( url, "matchcase" ) )
patternOptions |= QRegularExpression::CaseInsensitiveOption;
regexp.setPatternOptions( patternOptions );
@ -2470,18 +2513,17 @@ void ArticleView::highlightFTSResults()
if( regexp.pattern().isEmpty() || !regexp.isValid() )
return;
sptr< AccentMarkHandler > marksHandler = ignoreDiacritics ?
new DiacriticsHandler : new AccentMarkHandler;
sptr< AccentMarkHandler > marksHandler = ignoreDiacritics ? new DiacriticsHandler : new AccentMarkHandler;
// Clear any current selection
if( ui.definition->selectedText().size() )
{
ui.definition->page()->
runJavaScript( "window.getSelection().removeAllRanges();_=0;" );
ui.definition->page()->runJavaScript( "window.getSelection().removeAllRanges();_=0;" );
}
QString pageText = getWebPageTextSync(ui.definition->page());
ui.definition->page()->toPlainText(
[ & ]( const QString pageText )
{
marksHandler->setText( pageText );
QRegularExpressionMatchIterator it = regexp.globalMatch( marksHandler->normalizedText() );
@ -2495,14 +2537,14 @@ void ArticleView::highlightFTSResults()
int matched = marksHandler->mirrorPosition( pos + match.capturedLength() ) - spos;
// Add mark pos (if presented)
while( spos + matched < pageText.length()
&& pageText[ spos + matched ].category() == QChar::Mark_NonSpacing )
while( spos + matched < pageText.length() && pageText[ spos + matched ].category() == QChar::Mark_NonSpacing )
matched++;
if( matched > FTS::MaxMatchLengthForHighlightResults )
{
gdWarning( "ArticleView::highlightFTSResults(): Too long match - skipped (matched length %i, allowed %i)",
match.capturedLength(), FTS::MaxMatchLengthForHighlightResults );
match.capturedLength(),
FTS::MaxMatchLengthForHighlightResults );
}
else
allMatches.append( pageText.mid( spos, matched ) );
@ -2523,9 +2565,8 @@ void ArticleView::highlightFTSResults()
ui.definition->findText( allMatches.at( 0 ), flags );
// if( ui.definition->findText( allMatches.at( 0 ), flags ) )
{
ui.definition->page()->
runJavaScript( QString( "%1=window.getSelection().getRangeAt(0);_=0;" )
.arg( rangeVarName ) );
ui.definition->page()->runJavaScript(
QString( "%1=window.getSelection().getRangeAt(0);_=0;" ).arg( rangeVarName ) );
}
}
@ -2534,20 +2575,7 @@ void ArticleView::highlightFTSResults()
ui.ftsSearchNext->setEnabled( allMatches.size() > 1 );
ftsSearchIsOpened = true;
}
QString ArticleView::getWebPageTextSync(QWebEnginePage * page){
QString planText;
QSharedPointer<QEventLoop> loop = QSharedPointer<QEventLoop>(new QEventLoop());
QTimer::singleShot(1000, loop.data(), &QEventLoop::quit);
page->toPlainText([&](const QString &result)
{
if(loop->isRunning()){
planText = result;
loop->quit();
} });
loop->exec();
return planText;
} );
}
void ArticleView::setActiveDictIds(ActiveDictIds ad) {
@ -2589,7 +2617,18 @@ void ArticleView::performFtsFindOperation( bool backwards )
if (ftsPosition > 0) {
ftsPosition -= 1;
}
#if( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
ui.definition->findText( allMatches.at( ftsPosition ),
flags | QWebEnginePage::FindBackward,
[ this ]( const QWebEngineFindTextResult & result )
{
if( result.numberOfMatches ()== 0 )
return;
ui.ftsSearchPrevious->setEnabled(true);
if (!ui.ftsSearchNext->isEnabled())
ui.ftsSearchNext->setEnabled(true);
});
#else
ui.definition->findText(allMatches.at(ftsPosition),
flags | QWebEnginePage::FindBackward,
[this](bool res) {
@ -2597,10 +2636,21 @@ void ArticleView::performFtsFindOperation( bool backwards )
if (!ui.ftsSearchNext->isEnabled())
ui.ftsSearchNext->setEnabled(res);
});
#endif
} else {
if (ftsPosition < allMatches.size() - 1) {
ftsPosition += 1;
}
#if( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
ui.definition->findText(allMatches.at(ftsPosition), flags, [this](const QWebEngineFindTextResult & result ) {
if( result.numberOfMatches() == 0 )
return;
ui.ftsSearchNext->setEnabled(true);
if (!ui.ftsSearchPrevious->isEnabled())
ui.ftsSearchPrevious->setEnabled(true);
});
}
#else
ui.definition->findText(allMatches.at(ftsPosition), flags, [this](bool res) {
ui.ftsSearchNext->setEnabled(res);
@ -2608,7 +2658,7 @@ void ArticleView::performFtsFindOperation( bool backwards )
ui.ftsSearchPrevious->setEnabled(res);
});
}
#endif
// Store new highlighted selection
ui.definition->page()->
runJavaScript( QString( "%1=window.getSelection().getRangeAt(0);_=0;" )
@ -2625,148 +2675,6 @@ void ArticleView::on_ftsSearchNext_clicked()
performFtsFindOperation( false );
}
#ifdef Q_OS_WIN32
void ArticleView::readTag( const QString & from, QString & to, int & count )
{
QChar ch, prev_ch;
bool inQuote = false, inDoublequote = false;
to.append( ch = prev_ch = from[ count++ ] );
while( count < from.size() )
{
ch = from[ count ];
if( ch == '>' && !( inQuote || inDoublequote ) )
{
to.append( ch );
break;
}
if( ch == '\'' )
inQuote = !inQuote;
if( ch == '\"' )
inDoublequote = !inDoublequote;
to.append( prev_ch = ch );
count++;
}
}
QString ArticleView::insertSpans( QString const & html )
{
QChar ch;
QString newContent;
bool inSpan = false, escaped = false;
/// Enclose every word in string (exclude tags) with <span></span>
for( int i = 0; i < html.size(); i++ )
{
ch = html[ i ];
if( ch == '&' )
{
escaped = true;
if( inSpan )
{
newContent.append( "</span>" );
inSpan = false;
}
newContent.append( ch );
continue;
}
if( ch == '<' ) // Skip tag
{
escaped = false;
if( inSpan )
{
newContent.append( "</span>" );
inSpan = false;
}
readTag( html, newContent, i );
continue;
}
if( escaped )
{
if( ch == ';' )
escaped = false;
newContent.append( ch );
continue;
}
if( !inSpan && ( ch.isLetterOrNumber() || ch.isLowSurrogate() ) )
{
newContent.append( "<span>");
inSpan = true;
}
if( inSpan && !( ch.isLetterOrNumber() || ch.isLowSurrogate() ) )
{
newContent.append( "</span>");
inSpan = false;
}
if( ch.isLowSurrogate() )
{
newContent.append( ch );
ch = html[ ++i ];
}
newContent.append( ch );
if( ch == '-' && !( html[ i + 1 ] == ' ' || ( i > 0 && html[ i - 1 ] == ' ' ) ) )
newContent.append( "<span style=\"font-size:0pt\"> </span>" );
}
if( inSpan )
newContent.append( "</span>" );
return newContent;
}
QString ArticleView::checkElement( QWebEnginePage & page, QPoint const & pt )
{
return runJavaScriptSync(&page, QString(
" var a= document.elementFromPoint(%1,%2);"
"var nodename=a.nodeName.toLowerCase();"
"if(nodename==\"body\"||nodename==\"html\"||nodename==\"head\")"
"{"
" return '';"
"}"
"return a.textContent;")
.arg(pt.x())
.arg(pt.y()));
}
QString ArticleView::wordAtPoint( int x, int y )
{
QString word;
if( popupView )
return word;
QPoint pos = mapFromGlobal( QPoint( x, y ) );
//todo
QWebEnginePage *frame = ui.definition->page();
if( !frame )
return word;
QPointF scrollPoint=frame->scrollPosition();
QPoint posWithScroll = pos + QPoint((int)scrollPoint.x(),(int)scrollPoint.y());
/// Find target HTML element
QString nodeValue = runJavaScriptSync(frame, QString(
"var a= document.elementFromPoint(%1,%2);"
"var nodename=a.nodeName.toLowerCase();"
"if(nodename==\"body\"||nodename==\"html\"||nodename==\"head\")"
"{"
" return '';"
"}"
"return a.textContent;")
.arg(posWithScroll.x())
.arg(posWithScroll.y()));
return nodeValue;
}
#endif
ResourceToSaveHandler::ResourceToSaveHandler(ArticleView * view, QString const & fileName ) :
QObject( view ),
fileName( fileName ),

View file

@ -15,6 +15,10 @@
#include "groupcombobox.hh"
#include "ui_articleview.h"
#include "globalbroadcaster.h"
#include "article_inspect.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QRegExp>
#endif
class ResourceToSaveHandler;
class ArticleViewAgent ;
@ -45,7 +49,7 @@ class ArticleView: public QFrame
QString rangeVarName;
//used to hold the F12 inspect source view.
QWebEngineView *inspectView = nullptr;
ArticleInspector * inspector = nullptr;
/// Any resource we've decided to download off the dictionary gets stored here.
/// Full vector capacity is used for search requests, where we have to make
@ -108,8 +112,6 @@ public:
/// Returns "gdfrom-" + dictionaryId.
static QString scrollToFromDictionaryId( QString const & dictionaryId );
QString runJavaScriptSync(QWebEnginePage* frame, const QString& variable);
void emitJavascriptFinished();
/// Shows the definition of the given word with the given group.
@ -154,8 +156,6 @@ public:
/// Called when preference changes
void setSelectionBySingleClick( bool set );
QString getWebPageTextSync(QWebEnginePage * page);
public slots:
/// Goes back in history
@ -175,22 +175,23 @@ public:
{ ui.definition->reload(); }
/// Returns true if there's an audio reference on the page, false otherwise.
bool hasSound();
void hasSound( const std::function< void( bool has ) > & callback );
/// Plays the first audio reference on the page, if any.
void playSound();
void setZoomFactor( qreal factor )
{
if(ui.definition->zoomFactor()!=factor){
qDebug()<<"set zoom factor:"<<factor;
qreal existedFactor = ui.definition->zoomFactor();
if(!qFuzzyCompare(existedFactor,factor)){
qDebug()<<"zoom factor ,existed:"<<existedFactor<<"set:"<<factor;
ui.definition->setZoomFactor( factor );
ui.definition->page()->setZoomFactor(factor);
//ui.definition->page()->setZoomFactor(factor);
}
}
/// Returns current article's text in .html format
QString toHtml();
void toHtml( const std::function< void( QString & ) > & callback );
void setHtml(const QString& content, const QUrl& baseUrl);
void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl());
@ -302,7 +303,7 @@ public slots:
//aim to receive signal from html. the fragment url click to navigation through page wil not be intecepted by weburlinteceptor
Q_INVOKABLE void linkClickedInHtml( QUrl const & );
private slots:
void inspectElement();
void loadFinished( bool ok );
void loadProgress(int);
void handleTitleChanged( QString const & title );
@ -364,7 +365,7 @@ private:
/// Checks if the given article in form of "gdfrom-xxx" is inside a "website"
/// frame.
bool isFramedArticle( QString const & );
void isFramedArticle( QString const & article, const std::function< void( bool framed ) > & callback );
/// Checks if the given link is to be opened externally, as opposed to opening
/// it in-place.
@ -405,18 +406,6 @@ private:
// We need this to hide the search bar when we're showed
void showEvent( QShowEvent * );
#ifdef Q_OS_WIN32
/// Search inside web page for word under cursor
private:
QString insertSpans( QString const & html );
void readTag( QString const & from, QString & to, int & count );
QString checkElement( QWebEnginePage & elem, const QPoint & pt );
public:
QString wordAtPoint( int x, int y );
#endif
};
class ResourceToSaveHandler: public QObject

View file

@ -6,6 +6,8 @@
#include <QWebEngineView>
#include <QApplication>
#include <QTimer>
#include <QDialog>
#include <QMainWindow>
#ifdef Q_OS_WIN32
#include <qt_windows.h>
@ -14,8 +16,7 @@
ArticleWebView::ArticleWebView( QWidget *parent ):
QWebEngineView( parent ),
midButtonPressed( false ),
selectionBySingleClick( false ),
showInspectorDirectly( true )
selectionBySingleClick( false )
{
}
@ -26,6 +27,7 @@ ArticleWebView::~ArticleWebView()
void ArticleWebView::setUp( Config::Class * cfg )
{
this->cfg = cfg;
setZoomFactor(cfg->preferences.zoomFactor);
}
void ArticleWebView::triggerPageAction( QWebEnginePage::WebAction action, bool checked )
@ -33,15 +35,26 @@ void ArticleWebView::triggerPageAction( QWebEnginePage::WebAction action, bool c
QWebEngineView::triggerPageAction( action, checked );
}
QWebEngineView * ArticleWebView::createWindow( QWebEnginePage::WebWindowType type )
{
if(type==QWebEnginePage::WebWindowType::WebDialog)
{
QMainWindow * dlg = new QMainWindow( this );
QWebEngineView * view = new QWebEngineView( dlg );
dlg->setCentralWidget(view);
dlg->resize(400,400);
dlg->show();
return view;
}
return QWebEngineView::createWindow(type);
}
bool ArticleWebView::event( QEvent * event )
{
if (event->type() == QEvent::ChildAdded) {
if( event->type() == QEvent::ChildAdded )
{
QChildEvent * child_ev = static_cast< QChildEvent * >( event );
// // there is also QObject child that should be ignored here;
// // use only QOpenGLWidget child
// QOpenGLWidget *w = static_cast<QOpenGLWidget*>(child_ev->child());
child_ev->child()->installEventFilter( this );
}
@ -87,10 +100,17 @@ bool ArticleWebView::eventFilter(QObject *obj, QEvent *ev) {
if (ev->type() == QEvent::Wheel) {
QWheelEvent *pe = static_cast<QWheelEvent *>(ev);
wheelEvent(pe);
if ( pe->modifiers().testFlag( Qt::ControlModifier ) )
{
return true;
}
if (ev->type() == QEvent::FocusIn) {
}
if( ev->type() == QEvent::FocusIn )
{
QFocusEvent * pe = static_cast< QFocusEvent * >( ev );
focusInEvent( pe );
return true;
}
return QWebEngineView::eventFilter(obj, ev);
@ -98,7 +118,7 @@ bool ArticleWebView::eventFilter(QObject *obj, QEvent *ev) {
void ArticleWebView::mousePressEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::MidButton)
if (event->buttons() & Qt::MiddleButton)
midButtonPressed = true;
}
@ -127,10 +147,10 @@ void ArticleWebView::sendCustomMouseEvent( QEvent::Type type) {
}
void ArticleWebView::mouseReleaseEvent(QMouseEvent *event) {
bool noMidButton = !( event->buttons() & Qt::MidButton );
bool noMidButton = !( event->buttons() & Qt::MiddleButton );
if ( midButtonPressed & noMidButton )
midButtonPressed = false;
// if ( midButtonPressed & noMidButton )
// midButtonPressed = false;
}
void ArticleWebView::doubleClickAction(QMouseEvent *event) {
@ -169,7 +189,7 @@ void ArticleWebView::wheelEvent( QWheelEvent *ev )
SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &nLines, 0 );
if( nLines == WHEEL_PAGESCROLL )
{
QKeyEvent kev( QEvent::KeyPress, ev->delta() > 0 ? Qt::Key_PageUp : Qt::Key_PageDown,
QKeyEvent kev( QEvent::KeyPress, ev->angleDelta ().y () > 0 ? Qt::Key_PageUp : Qt::Key_PageDown,
Qt::NoModifier );
auto childrens = this->children();
for (auto child : childrens) {

View file

@ -8,7 +8,6 @@
#include <QEvent>
#include <QMouseEvent>
#include <QWebEngineView>
#include <QOpenGLWidget>
#include <QPointer>
/// A thin wrapper around QWebEngineView to accommodate to some ArticleView's needs.
@ -17,8 +16,6 @@
/// to the view's current state. This is used to open links in new tabs when
/// they are clicked with middle button. There's also an added possibility to
/// get double-click events after the fact with the doubleClicked() signal.
/// 2. Manage our own QWebInspector instance. In order to show inspector correctly,
/// use triggerPageAction( QWebEnginePage::InspectElement ) instead.
class ArticleWebView: public QWebEngineView
{
Q_OBJECT
@ -27,11 +24,14 @@ public:
ArticleWebView( QWidget * parent );
~ArticleWebView();
void setUp( Config::Class * cfg );
bool isMidButtonPressed() const
{ return midButtonPressed; }
void resetMidButtonPressed()
{
midButtonPressed = false;
}
void setSelectionBySingleClick( bool set )
{ selectionBySingleClick = set; }
@ -48,7 +48,7 @@ public:
void doubleClicked( QPoint pos );
protected:
QWebEngineView *createWindow(QWebEnginePage::WebWindowType type);
bool event( QEvent * event );
void singleClickAction(QMouseEvent *event);
void sendCustomMouseEvent(QEvent::Type type);
@ -66,7 +66,6 @@ private:
bool midButtonPressed;
bool selectionBySingleClick;
bool showInspectorDirectly;
//MouseDbClickEvent will also emit MousePressEvent which conflict the single click event.
//this variable used to distinguish the single click and real double click.

View file

@ -0,0 +1,23 @@
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
CONFIG += qtestlib
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
HEADERS+= \
../iconv.hh \
../wstring.hh \
../wstring_qt.hh
SOURCES += \
test-qtextcodec-convert.cpp \
../iconv.cc \
../wstring_qt.cc
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

View file

@ -0,0 +1,49 @@
#include <QTest>
#include <QDate>
#include "../iconv.hh"
#include <string>
#include "../wstring_qt.hh"
//used to test Iconv.cc
class testQTextCodec : public QObject
{
Q_OBJECT
private slots:
void testConvert();
void testToWstring();
void testToUtf8();
};
void testQTextCodec::testConvert()
{
Iconv conv( "utf-8", Iconv::GdWchar );
const char s[] = { 0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00 };
void const * in = &s[ 0 ];
size_t len = 12;
QString r = conv.convert( in, len );
QCOMPARE( r, "abc" );
}
void testQTextCodec::testToWstring()
{
const char s[] = { 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x63 };
gd::wstring r1 = Iconv::toWstring( "UTF-32BE", s, 12 );
QCOMPARE( r1.size(), 3 );
QCOMPARE( r1, U"abc" );
char32_t * arr = (char32_t*)r1.c_str ();
QCOMPARE( arr[ 0 ], 0x00000061 );
}
void testQTextCodec::testToUtf8()
{
const char s[] = { 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x63 };
std::string r1 = Iconv::toUtf8 ( "UTF-32BE", s, 12 );
QCOMPARE( r1.size(), 3 );
QCOMPARE( r1, u8"abc" );
char * arr = (char*)r1.c_str ();
QCOMPARE( arr[ 0 ], 0x61 );
}
QTEST_MAIN(testQTextCodec)
#include "test-qtextcodec-convert.moc"

View file

@ -406,7 +406,7 @@ public:
}
};
std::vector< sptr< Dictionary::Class > > makeDictionaries() THROW_SPEC( std::exception )
std::vector< sptr< Dictionary::Class > > makeDictionaries()
{
static BelarusianLatinToClassicTable t0;
static BelarusianLatinToSchoolTable t1;

View file

@ -10,7 +10,7 @@
// Support for Belarusian transliteration
namespace BelarusianTranslit {
std::vector< sptr< Dictionary::Class > > makeDictionaries() THROW_SPEC( std::exception );
std::vector< sptr< Dictionary::Class > > makeDictionaries() ;
}

37
bgl.cc
View file

@ -31,7 +31,11 @@
#include <QAtomicInt>
#include <QDebug>
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QRegExp>
#else
#include <QRegExp>
#endif
#include <QRegularExpression>
@ -174,20 +178,7 @@ namespace
}
// Convert the word from utf8 to wide chars
if ( wcharBuffer.size() <= word.size() )
wcharBuffer.resize( word.size() + 1 );
long result = Utf8::decode( word.c_str(), word.size(),
&wcharBuffer.front() );
if ( result < 0 )
{
gdWarning( "Failed to decode utf8 of headword \"%s\", skipping it.", word.c_str() );
return;
}
indexedWords.addWord( wstring( &wcharBuffer.front(), result ), articleOffset );
indexedWords.addWord( Utf8::decode( word ), articleOffset );
}
@ -226,16 +217,16 @@ namespace
{ return idxHeader.langTo; }
virtual sptr< Dictionary::WordSearchRequest > findHeadwordsForSynonym( wstring const & )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getResource( string const & name )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString,
int searchMode, bool matchCase,
@ -609,7 +600,7 @@ void BglHeadwordsRequest::run()
sptr< Dictionary::WordSearchRequest >
BglDictionary::findHeadwordsForSynonym( wstring const & word )
THROW_SPEC( std::exception )
{
return synonymSearchEnabled ? new BglHeadwordsRequest( word, *this ) :
Class::findHeadwordsForSynonym( word );
@ -933,7 +924,7 @@ sptr< Dictionary::DataRequest > BglDictionary::getArticle( wstring const & word,
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception )
{
return new BglArticleRequest( word, alts, *this, ignoreDiacritics );
}
@ -1077,7 +1068,7 @@ void BglResourceRequest::run()
}
sptr< Dictionary::DataRequest > BglDictionary::getResource( string const & name )
THROW_SPEC( std::exception )
{
return new BglResourceRequest( idxMutex, idx, idxHeader.resourceListOffset,
idxHeader.resourcesCount, name );
@ -1100,7 +1091,7 @@ sptr< Dictionary::DataRequest > BglDictionary::getResource( string const & name
while( it.hasNext() )
{
QRegularExpressionMatch match = it.next();
result += str.midRef( pos, match.capturedStart() - pos );
result += str.mid( pos, match.capturedStart() - pos );
pos = match.capturedEnd();
QRegularExpressionMatchIterator itValue = oneValueExp.globalMatch( match.captured( 1 ) );
@ -1113,7 +1104,7 @@ sptr< Dictionary::DataRequest > BglDictionary::getResource( string const & name
if( pos )
{
result += str.midRef( pos );
result += str.mid( pos );
str = result;
}
@ -1178,7 +1169,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
Dictionary::Initializing & initializing )
THROW_SPEC( std::exception )
{
vector< sptr< Dictionary::Class > > dictionaries;

2
bgl.hh
View file

@ -23,7 +23,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
Dictionary::Initializing & )
THROW_SPEC( std::exception );
;
}

View file

@ -27,7 +27,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <iconv.h>
#include <QTextDocument>
#include "gddebug.hh"
#include "ufile.hh"
@ -36,6 +35,7 @@
#include <QString>
#include <QDebug>
#include "dictionary.hh"
#include "wstring_qt.hh"
#ifdef _WIN32
#include <io.h>
@ -198,6 +198,7 @@ bool Babylon::read(std::string &source_charset, std::string &target_charset)
{
headword.clear();
definition.clear();
switch( block.type )
{
case 0:
@ -534,7 +535,7 @@ bgl_entry Babylon::readEntry( ResourceHandler * resourceHandler )
{
try
{
transcription = Iconv::toUtf8( "CP1252", block.data + pos + 3, length );
transcription = Iconv::toUtf8( "Windows-1252", block.data + pos + 3, length );
}
catch( Iconv::Ex & e )
{
@ -565,7 +566,7 @@ bgl_entry Babylon::readEntry( ResourceHandler * resourceHandler )
{
try
{
transcription = Iconv::toUtf8( "CP1252", block.data + pos + 4, length );
transcription = Iconv::toUtf8( "Windows-1252", block.data + pos + 4, length );
}
catch( Iconv::Ex & e )
{
@ -759,42 +760,14 @@ void Babylon::convertToUtf8( std::string &s, unsigned int type )
if( charset == "UTF-8" )
return;
iconv_t cd = iconv_open( "UTF-8", charset.c_str() );
if( cd == (iconv_t)(-1) )
throw exIconv();
Iconv conv_("UTF-8", charset.c_str());
char *outbuf, *defbuf;
size_t inbufbytes, outbufbytes;
inbufbytes = s.size();
outbufbytes = s.size() * 6;
size_t inbufbytes = s.size();
char *inbuf;
inbuf = (char *)s.data();
outbuf = (char*)malloc( outbufbytes + 1 );
if( !outbuf )
{
iconv_close( cd );
throw exAllocation();
}
const void* test = inbuf;
memset( outbuf, '\0', outbufbytes + 1 );
defbuf = outbuf;
while (inbufbytes) {
if (iconv(cd, &inbuf, &inbufbytes, &outbuf, &outbufbytes) == (size_t)-1) {
gdWarning( "\"%s\" - error in iconv conversion (%s)\n", inbuf, strerror( errno ) );
break;
// inbuf++;
// inbufbytes--;
}
}
// Flush the state. This fixes CP1255 problems.
iconv( cd, 0, 0, &outbuf, &outbufbytes );
if( inbufbytes == 0 )
s = std::string( defbuf );
free( defbuf );
iconv_close( cd );
QString convStr = conv_.convert(test,inbufbytes);
s = gd::toStdString(convStr);
}

View file

@ -27,11 +27,7 @@
#include <string>
#include <vector>
#include <qglobal.h>
#if defined( _MSC_VER ) && _MSC_VER < 1800 // VS2012 and older
#include <stdint_msvc.h>
#else
#include <stdint.h>
#endif
//const std::string bgl_language[] = {
#ifndef blgCode2Int

View file

@ -8,8 +8,12 @@
#ifdef HAVE_X11
#include <X11/Xlib.h>
#include <X11/extensions/record.h>
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtGui/private/qtx11extras_p.h>
#else
#include <QX11Info>
#endif
#endif
bool isRECORDBroken()
{

View file

@ -462,7 +462,7 @@ BtreeWordSearchRequest::~BtreeWordSearchRequest()
sptr< Dictionary::WordSearchRequest > BtreeDictionary::prefixMatch(
wstring const & str, unsigned long maxResults )
THROW_SPEC( std::exception )
{
return new BtreeWordSearchRequest( *this, str, 0, -1, true, maxResults );
}
@ -470,7 +470,7 @@ sptr< Dictionary::WordSearchRequest > BtreeDictionary::prefixMatch(
sptr< Dictionary::WordSearchRequest > BtreeDictionary::stemmedMatch(
wstring const & str, unsigned minLength, unsigned maxSuffixVariation,
unsigned long maxResults )
THROW_SPEC( std::exception )
{
return new BtreeWordSearchRequest( *this, str, minLength, (int)maxSuffixVariation,
false, maxResults );
@ -526,8 +526,8 @@ char const * BtreeIndex::findChainOffsetExactOrPrefix( wstring const & target,
// Lookup the index by traversing the index btree
vector< wchar > wcharBuffer;
// vector< wchar > wcharBuffer;
wstring w_word;
exactMatch = false;
// Read a node
@ -616,19 +616,9 @@ char const * BtreeIndex::findChainOffsetExactOrPrefix( wstring const & target,
size_t wordSize = strlen( closestString );
if ( wcharBuffer.size() <= wordSize )
wcharBuffer.resize( wordSize + 1 );
w_word = Utf8::decode( string( closestString, wordSize ) );
long result = Utf8::decode( closestString, wordSize, &wcharBuffer.front() );
if ( result < 0 )
throw Utf8::exCantDecode( closestString );
wcharBuffer[ result ] = 0;
//GD_DPRINTF( "Checking against %s\n", closestString );
compareResult = target.compare( &wcharBuffer.front() );
compareResult = target.compare( w_word);
if ( !compareResult )
{
@ -750,21 +740,11 @@ char const * BtreeIndex::findChainOffsetExactOrPrefix( wstring const & target,
size_t wordSize = strlen( ptr );
if ( wcharBuffer.size() <= wordSize )
wcharBuffer.resize( wordSize + 1 );
w_word = Utf8::decode( string( ptr, wordSize ) );
//GD_DPRINTF( "checking against word %s, left = %u\n", ptr, leafEntries );
long result = Utf8::decode( ptr, wordSize, &wcharBuffer.front() );
if ( result < 0 )
throw Utf8::exCantDecode( ptr );
wcharBuffer[ result ] = 0;
wstring foldedWord = Folding::apply( &wcharBuffer.front() );
wstring foldedWord = Folding::apply( w_word );
if( foldedWord.empty() )
foldedWord = Folding::applyWhitespaceOnly( &wcharBuffer.front() );
foldedWord = Folding::applyWhitespaceOnly( w_word );
int compareResult = target.compare( foldedWord );
@ -1073,20 +1053,8 @@ void IndexedWords::addWord( wstring const & word, uint32_t articleOffset, unsign
// which are freakishly huge.
if( wordSize > maxHeadwordSize )
{
#define MAX_LOG_WORD_SIZE 500
string headword;
if( wordSize <= MAX_LOG_WORD_SIZE )
headword = Utf8::encode( word );
else
{
std::vector< char > buffer( MAX_LOG_WORD_SIZE * 4 );
headword = string( &buffer.front(),
Utf8::encode( wordBegin, MAX_LOG_WORD_SIZE, &buffer.front() ) );
headword += "...";
}
gdWarning( "Skipped too long headword: \"%s\"", headword.c_str() );
qWarning() << "Skipped too long headword: " << word.substr( 0, 100 ).c_str() << "size:" << wordSize;
return;
#undef MAX_LOG_WORD_SIZE
}
// Skip any leading whitespace
@ -1118,17 +1086,11 @@ void IndexedWords::addWord( wstring const & word, uint32_t articleOffset, unsign
wstring folded = Folding::applyWhitespaceOnly( wstring( wordBegin, wordSize ) );
if( !folded.empty() )
{
iterator i = insert(
IndexedWords::value_type(
string( &utfBuffer.front(),
Utf8::encode( folded.data(), folded.size(), &utfBuffer.front() ) ),
vector< WordArticleLink >() ) ).first;
iterator i = insert( { Utf8::encode( folded ),
vector< WordArticleLink >() } )
.first;
// Try to conserve memory somewhat -- slow insertions are ok
i->second.reserve( i->second.size() + 1 );
string utfWord( &utfBuffer.front(),
Utf8::encode( wordBegin, wordSize, &utfBuffer.front() ) );
string utfWord=Utf8::encode( wstring(wordBegin, wordSize )) ;
string utfPrefix;
i->second.push_back( WordArticleLink( utfWord, articleOffset, utfPrefix ) );
}
@ -1143,22 +1105,13 @@ void IndexedWords::addWord( wstring const & word, uint32_t articleOffset, unsign
// Insert this word
wstring folded = Folding::apply( nextChar );
iterator i = insert(
IndexedWords::value_type(
string( &utfBuffer.front(),
Utf8::encode( folded.data(), folded.size(), &utfBuffer.front() ) ),
vector< WordArticleLink >() ) ).first;
iterator i = insert( { Utf8::encode( folded ), vector< WordArticleLink >() } ).first;
if( ( i->second.size() < 1024 ) || ( nextChar == wordBegin ) ) // Don't overpopulate chains with middle matches
{
// Try to conserve memory somewhat -- slow insertions are ok
i->second.reserve( i->second.size() + 1 );
string utfWord = Utf8::encode( wstring( nextChar, wordSize - ( nextChar - wordBegin ) ) );
string utfWord( &utfBuffer.front(),
Utf8::encode( nextChar, wordSize - ( nextChar - wordBegin ), &utfBuffer.front() ) );
string utfPrefix( &utfBuffer.front(),
Utf8::encode( wordBegin, nextChar - wordBegin, &utfBuffer.front() ) );
string utfPrefix = Utf8::encode( wstring( wordBegin, nextChar - wordBegin ) );
i->second.push_back( WordArticleLink( utfWord, articleOffset, utfPrefix ) );
}
@ -1437,8 +1390,9 @@ void BtreeIndex::getHeadwordsFromOffsets( QList<uint32_t> & offsets,
for( unsigned i = 0; i < result.size(); i++ )
{
QList< uint32_t >::Iterator it = qBinaryFind( begOffsets, endOffsets,
result.at( i ).articleOffset );
uint32_t articleOffset = result.at(i).articleOffset;
QList<uint32_t>::Iterator it = std::lower_bound( begOffsets, endOffsets,
articleOffset );
if( it!=offsets.end())
{

View file

@ -14,13 +14,8 @@
#include <QVector>
#include <QSet>
#include <QList>
#include "cpp_features.hh"
#if defined( _MSC_VER ) && _MSC_VER < 1800 // VS2012 and older
#include <stdint_msvc.h>
#else
#include <stdint.h>
#endif
/// A base for the dictionary which creates a btree index to look up
/// the words.
@ -167,13 +162,13 @@ public:
/// need not to implement this function.
virtual sptr< Dictionary::WordSearchRequest > prefixMatch( wstring const &,
unsigned long )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::WordSearchRequest > stemmedMatch( wstring const &,
unsigned minLength,
unsigned maxSuffixVariation,
unsigned long maxResults )
THROW_SPEC( std::exception );
;
virtual bool isLocalDictionary()
{ return true; }

View file

@ -4,11 +4,11 @@
#include "chinese.hh"
#include <stdexcept>
#include <QCoreApplication>
#ifdef Q_OS_MAC
// #ifdef Q_OS_MAC
#include <opencc/opencc.h>
#endif
// #endif
#include <opencc/Export.hpp>
#include <opencc/SimpleConverter.hpp>
// #include <opencc/SimpleConverter.hpp>
#include "folding.hh"
#include "gddebug.hh"
#include "transliteration.hh"
@ -18,11 +18,11 @@ namespace Chinese {
class CharacterConversionDictionary: public Transliteration::BaseTransliterationDictionary
{
#ifdef Q_OS_MAC
// #ifdef Q_OS_MAC
opencc_t converter;
#else
opencc::SimpleConverter* converter;
#endif
// #else
// opencc::SimpleConverter* converter;
// #endif
public:
@ -42,16 +42,16 @@ CharacterConversionDictionary::CharacterConversionDictionary( std::string const
converter( NULL )
{
try {
#ifdef Q_OS_MAC
// #ifdef Q_OS_MAC
converter = opencc_open( openccConfig.toLocal8Bit().constData() );
if( converter == reinterpret_cast< opencc_t >( -1 ) )
{
gdWarning( "CharacterConversionDictionary: failed to initialize OpenCC from config %s: %s\n",
openccConfig.toLocal8Bit().constData(), opencc_error() );
}
#else
converter = new opencc::SimpleConverter( openccConfig.toLocal8Bit().constData() );
#endif
// #else
// converter = new opencc::SimpleConverter( openccConfig.toLocal8Bit().constData() );
// #endif
} catch ( std::runtime_error& e ) {
gdWarning( "CharacterConversionDictionary: failed to initialize OpenCC from config %s: %s\n",
openccConfig.toLocal8Bit().constData(), e.what() );
@ -60,13 +60,13 @@ CharacterConversionDictionary::CharacterConversionDictionary( std::string const
CharacterConversionDictionary::~CharacterConversionDictionary()
{
#ifdef Q_OS_MAC
// #ifdef Q_OS_MAC
if ( converter != NULL && converter != reinterpret_cast< opencc_t >( -1 ) )
opencc_close( converter );
#else
if ( converter != NULL )
delete converter;
#endif
// #else
// if ( converter != NULL )
// delete converter;
// #endif
}
std::vector< gd::wstring > CharacterConversionDictionary::getAlternateWritings( gd::wstring const & str )
@ -81,7 +81,7 @@ std::vector< gd::wstring > CharacterConversionDictionary::getAlternateWritings(
gd::wstring result;
try {
#ifdef Q_OS_MAC
// #ifdef Q_OS_MAC
if ( converter != NULL && converter != reinterpret_cast< opencc_t >( -1 ) )
{
char * tmp = opencc_convert_utf8( converter, input.c_str(), input.length() );
@ -93,9 +93,9 @@ std::vector< gd::wstring > CharacterConversionDictionary::getAlternateWritings(
else
gdWarning( "OpenCC: conversion failed %s\n", opencc_error() );
}
#else
output = converter->Convert( input );
#endif
// #else
// output = converter->Convert( input );
// #endif
result = Utf8::decode( output );
} catch ( std::exception& ex ) {
gdWarning( "OpenCC: conversion failed %s\n", ex.what() );
@ -109,7 +109,7 @@ std::vector< gd::wstring > CharacterConversionDictionary::getAlternateWritings(
}
std::vector< sptr< Dictionary::Class > > makeDictionaries( Config::Chinese const & cfg )
THROW_SPEC( std::exception )
{
std::vector< sptr< Dictionary::Class > > result;

View file

@ -12,7 +12,7 @@
namespace Chinese {
std::vector< sptr< Dictionary::Class > > makeDictionaries( Config::Chinese const & )
THROW_SPEC( std::exception );
;
}

View file

@ -8,11 +8,7 @@
#include "file.hh"
#include <vector>
#if defined( _MSC_VER ) && _MSC_VER < 1800 // VS2012 and older
#include <stdint_msvc.h>
#else
#include <stdint.h>
#endif
/// A chunked compression storage. We use this for articles' bodies. The idea
/// is to store data in a separately-compressed chunks, much like in dictzip,

View file

@ -9,11 +9,7 @@
#include <QtXml>
#include "gddebug.hh"
#if defined( _MSC_VER ) && _MSC_VER < 1800 // VS2012 and older
#include <stdint_msvc.h>
#else
#include <stdint.h>
#endif
#ifdef Q_OS_WIN32
#include "shlobj.h"
@ -217,6 +213,7 @@ Preferences::Preferences():
autoStart( false ),
doubleClickTranslates( true ),
selectWordBySingleClick( false ),
autoScrollToTargetArticle( true ),
escKeyHidesMainWindow( false ),
alwaysOnTop ( false ),
searchInDock ( false ),
@ -446,7 +443,7 @@ void saveMutedDictionaries( QDomDocument & dd, QDomElement & muted,
}
Class load() THROW_SPEC( exError )
Class load()
{
QString configName = getConfigFileName();
@ -862,6 +859,9 @@ Class load() THROW_SPEC( exError )
if ( !preferences.namedItem( "selectWordBySingleClick" ).isNull() )
c.preferences.selectWordBySingleClick = ( preferences.namedItem( "selectWordBySingleClick" ).toElement().text() == "1" );
if ( !preferences.namedItem( "autoScrollToTargetArticle" ).isNull() )
c.preferences.autoScrollToTargetArticle = ( preferences.namedItem( "autoScrollToTargetArticle" ).toElement().text() == "1" );
if ( !preferences.namedItem( "escKeyHidesMainWindow" ).isNull() )
c.preferences.escKeyHidesMainWindow = ( preferences.namedItem( "escKeyHidesMainWindow" ).toElement().text() == "1" );
@ -1278,7 +1278,7 @@ void saveGroup( Group const & data, QDomElement & group )
}
void save( Class const & c ) THROW_SPEC( exError )
void save( Class const & c )
{
QFile configFile( getConfigFileName() + ".tmp" );
@ -1725,6 +1725,10 @@ void save( Class const & c ) THROW_SPEC( exError )
opt.appendChild( dd.createTextNode( c.preferences.selectWordBySingleClick ? "1":"0" ) );
preferences.appendChild( opt );
opt = dd.createElement( "autoScrollToTargetArticle" );
opt.appendChild( dd.createTextNode( c.preferences.autoScrollToTargetArticle ? "1":"0" ) );
preferences.appendChild( opt );
opt = dd.createElement( "escKeyHidesMainWindow" );
opt.appendChild( dd.createTextNode( c.preferences.escKeyHidesMainWindow ? "1":"0" ) );
preferences.appendChild( opt );
@ -2202,12 +2206,12 @@ QString getConfigFileName()
return getHomeDir().absoluteFilePath( "config" );
}
QString getConfigDir() THROW_SPEC( exError )
QString getConfigDir()
{
return getHomeDir().path() + QDir::separator();
}
QString getIndexDir() THROW_SPEC( exError )
QString getIndexDir()
{
QDir result = getHomeDir();
@ -2228,12 +2232,12 @@ QString getIndexDir() THROW_SPEC( exError )
return result.path() + QDir::separator();
}
QString getPidFileName() THROW_SPEC( exError )
QString getPidFileName()
{
return getHomeDir().filePath( "pid" );
}
QString getHistoryFileName() THROW_SPEC( exError )
QString getHistoryFileName()
{
QString homeHistoryPath = getHomeDir().filePath( "history" );
@ -2249,22 +2253,22 @@ QString getHistoryFileName() THROW_SPEC( exError )
return homeHistoryPath;
}
QString getFavoritiesFileName() THROW_SPEC( exError )
QString getFavoritiesFileName()
{
return getHomeDir().filePath( "favorites" );
}
QString getUserCssFileName() THROW_SPEC( exError )
QString getUserCssFileName()
{
return getHomeDir().filePath( "article-style.css" );
}
QString getUserCssPrintFileName() THROW_SPEC( exError )
QString getUserCssPrintFileName()
{
return getHomeDir().filePath( "article-style-print.css" );
}
QString getUserQtCssFileName() THROW_SPEC( exError )
QString getUserQtCssFileName()
{
return getHomeDir().filePath( "qt-style.css" );
}
@ -2281,6 +2285,11 @@ QString getProgramDataDir() throw()
#endif
}
QString getEmbedLocDir() throw()
{
return ":/locale";
}
QString getLocDir() throw()
{
if ( QDir( getProgramDataDir() ).cd( "locale" ) )
@ -2348,7 +2357,7 @@ QString getPortableVersionMorphoDir() throw()
return QString();
}
QString getStylesDir() throw()
QString getStylesDir()
{
QDir result = getHomeDir();

View file

@ -12,7 +12,6 @@
#include <QKeySequence>
#include <QSet>
#include <QMetaType>
#include "cpp_features.hh"
#include "ex.hh"
#ifdef Q_OS_WIN
@ -293,6 +292,7 @@ struct Preferences
bool autoStart;
bool doubleClickTranslates;
bool selectWordBySingleClick;
bool autoScrollToTargetArticle;
bool escKeyHidesMainWindow;
bool alwaysOnTop;
@ -763,44 +763,45 @@ DEF_EX( exCantWriteConfigFile, "Can't write the configuration file", exError )
DEF_EX( exMalformedConfigFile, "The configuration file is malformed", exError )
/// Loads the configuration, or creates the default one if none is present
Class load() THROW_SPEC( exError );
Class load() ;
/// Saves the configuration
void save( Class const & ) THROW_SPEC( exError );
void save( Class const & ) ;
/// Returns the configuration file name.
QString getConfigFileName();
/// Returns the main configuration directory.
QString getConfigDir() THROW_SPEC( exError );
QString getConfigDir() ;
/// Returns the index directory, where the indices are to be stored.
QString getIndexDir() THROW_SPEC( exError );
QString getIndexDir() ;
/// Returns the filename of a .pid file which should store current pid of
/// the process.
QString getPidFileName() THROW_SPEC( exError );
QString getPidFileName() ;
/// Returns the filename of a history file which stores search history.
QString getHistoryFileName() THROW_SPEC( exError );
QString getHistoryFileName() ;
/// Returns the filename of a favorities file.
QString getFavoritiesFileName() THROW_SPEC( exError );
QString getFavoritiesFileName() ;
/// Returns the user .css file name.
QString getUserCssFileName() THROW_SPEC( exError );
QString getUserCssFileName() ;
/// Returns the user .css file name used for printing only.
QString getUserCssPrintFileName() THROW_SPEC( exError );
QString getUserCssPrintFileName() ;
/// Returns the user .css file name for the Qt interface customization.
QString getUserQtCssFileName() THROW_SPEC( exError );
QString getUserQtCssFileName() ;
/// Returns the program's data dir. Under Linux that would be something like
/// /usr/share/apps/goldendict, under Windows C:/Program Files/GoldenDict.
QString getProgramDataDir() throw();
/// Returns the directory storing program localizized files (.qm).
QString getEmbedLocDir() throw();
QString getLocDir() throw();
/// Returns the directory storing program help files (.qch).
@ -824,7 +825,7 @@ QString getPortableVersionDictionaryDir() throw();
QString getPortableVersionMorphoDir() throw();
/// Returns the add-on styles directory.
QString getStylesDir() throw();
QString getStylesDir();
/// Returns the directory where user-specific non-essential (cached) data should be written.
QString getCacheDir() throw();

View file

@ -1,10 +0,0 @@
#ifndef __CPP_HH_INCLUDED__
#define __CPP_HH_INCLUDED__
#if __cplusplus > 199711L
#define THROW_SPEC(...)
#else
#define THROW_SPEC(...) throw(__VA_ARGS__)
#endif
#endif // CPP_HH

View file

@ -1,4 +1,4 @@
#include <QStyleOptionViewItemV4>
#include <QStyleOptionViewItem>
#include "delegate.hh"

View file

@ -124,7 +124,7 @@ public:
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception );
;
virtual QString const& getDescription();
@ -258,7 +258,7 @@ sptr< Dictionary::DataRequest > DictdDictionary::getArticle( wstring const & wor
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception )
{
try
{
@ -371,7 +371,7 @@ sptr< Dictionary::DataRequest > DictdDictionary::getArticle( wstring const & wor
while( it.hasNext() )
{
QRegularExpressionMatch match = it.next();
articleNewString += articleString.midRef( pos, match.capturedStart() - pos );
articleNewString += articleString.mid( pos, match.capturedStart() - pos );
pos = match.capturedEnd();
QString link = match.captured( 1 );
@ -385,7 +385,7 @@ sptr< Dictionary::DataRequest > DictdDictionary::getArticle( wstring const & wor
}
if( pos )
{
articleNewString += articleString.midRef( pos );
articleNewString += articleString.mid( pos );
articleString = articleNewString;
articleNewString.clear();
}
@ -450,8 +450,8 @@ QString const& DictdDictionary::getDescription()
if( !dictionaryDescription.isEmpty() )
return dictionaryDescription;
sptr< Dictionary::DataRequest > req = getArticle( GD_NATIVE_TO_WS( L"00databaseinfo" ),
vector< wstring >(), wstring(), false );
sptr< Dictionary::DataRequest > req =
getArticle( U"00databaseinfo" , vector< wstring >(), wstring(), false );
if( req->dataSize() > 0 )
dictionaryDescription = Html::unescape( QString::fromUtf8( req->getFullData().data(), req->getFullData().size() ), true );
@ -583,7 +583,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
Dictionary::Initializing & initializing )
THROW_SPEC( std::exception )
{
vector< sptr< Dictionary::Class > > dictionaries;

View file

@ -16,7 +16,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
Dictionary::Initializing & )
THROW_SPEC( std::exception );
;
}

View file

@ -6,6 +6,9 @@
#include "mainwindow.hh"
#include <QRegExp>
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat>
#endif
#include <QDir>
#include <QFileDialog>
#include <QTimer>

View file

@ -73,7 +73,7 @@ size_t WordSearchRequest::matchesCount()
return matches.size();
}
WordMatch WordSearchRequest::operator [] ( size_t index ) THROW_SPEC( exIndexOutOfRange )
WordMatch WordSearchRequest::operator [] ( size_t index )
{
Mutex::Lock _( dataMutex );
@ -83,7 +83,7 @@ WordMatch WordSearchRequest::operator [] ( size_t index ) THROW_SPEC( exIndexOut
return matches[ index ];
}
vector< WordMatch > & WordSearchRequest::getAllMatches() THROW_SPEC( exRequestUnfinished )
vector< WordMatch > & WordSearchRequest::getAllMatches()
{
if ( !isFinished() )
throw exRequestUnfinished();
@ -112,7 +112,7 @@ long DataRequest::dataSize()
}
void DataRequest::getDataSlice( size_t offset, size_t size, void * buffer )
THROW_SPEC( exSliceOutOfRange )
{
if ( size == 0 )
return;
@ -125,7 +125,7 @@ void DataRequest::getDataSlice( size_t offset, size_t size, void * buffer )
memcpy( buffer, &data[ offset ], size );
}
vector< char > & DataRequest::getFullData() THROW_SPEC( exRequestUnfinished )
vector< char > & DataRequest::getFullData()
{
if ( !isFinished() )
throw exRequestUnfinished();
@ -147,13 +147,13 @@ sptr< WordSearchRequest > Class::stemmedMatch( wstring const & /*str*/,
unsigned /*minLength*/,
unsigned /*maxSuffixVariation*/,
unsigned long /*maxResults*/ )
THROW_SPEC( std::exception )
{
return new WordSearchRequestInstant();
}
sptr< WordSearchRequest > Class::findHeadwordsForSynonym( wstring const & )
THROW_SPEC( std::exception )
{
return new WordSearchRequestInstant();
}
@ -165,7 +165,7 @@ vector< wstring > Class::getAlternateWritings( wstring const & )
}
sptr< DataRequest > Class::getResource( string const & /*name*/ )
THROW_SPEC( std::exception )
{
return new DataRequestInstant( false );
}
@ -487,13 +487,13 @@ bool needToRebuildIndex( vector< string > const & dictionaryFiles,
ZipFile::SplitZipFile zf( name );
if( !zf.exists() )
return true;
ts = zf.lastModified().toTime_t();
ts = zf.lastModified().toSecsSinceEpoch();
}
else
{
if ( !fileInfo.exists() )
return true;
ts = fileInfo.lastModified().toTime_t();
ts = fileInfo.lastModified().toSecsSinceEpoch();
}
if ( ts > lastModified )
@ -505,7 +505,7 @@ bool needToRebuildIndex( vector< string > const & dictionaryFiles,
if ( !fileInfo.exists() )
return true;
return fileInfo.lastModified().toTime_t() < lastModified;
return fileInfo.lastModified().toSecsSinceEpoch() < lastModified;
}
QString generateRandomDictionaryId()
@ -516,5 +516,14 @@ QString generateRandomDictionaryId()
QCryptographicHash::Md5 ).toHex() );
}
QMap< std::string, sptr< Dictionary::Class > >
dictToMap( std::vector< sptr< Dictionary::Class > > const & dicts )
{
QMap< std::string, sptr< Dictionary::Class > > dictMap;
for( auto dict : dicts )
{
dictMap.insert( dict.get()->getId(), dict );
}
return dictMap;
}
}

View file

@ -9,7 +9,6 @@
#include <map>
#include <QObject>
#include <QIcon>
#include "cpp_features.hh"
#include "sptr.hh"
#include "ex.hh"
#include "mutex.hh"
@ -144,11 +143,11 @@ public:
/// Returns the match with the given zero-based index, which should be less
/// than matchesCount().
WordMatch operator [] ( size_t index ) THROW_SPEC( exIndexOutOfRange );
WordMatch operator [] ( size_t index ) ;
/// Returns all the matches found. Since no further locking can or would be
/// done, this can only be called after the request has finished.
vector< WordMatch > & getAllMatches() THROW_SPEC( exRequestUnfinished );
vector< WordMatch > & getAllMatches() ;
/// Returns true if the match was uncertain -- that is, there may be more
/// results in the dictionary itself, the dictionary index isn't good enough
@ -188,11 +187,11 @@ public:
/// Writes "size" bytes starting from "offset" of the data read to the given
/// buffer. "size + offset" must be <= than dataSize().
void getDataSlice( size_t offset, size_t size, void * buffer )
THROW_SPEC( exSliceOutOfRange );
;
/// Returns all the data read. Since no further locking can or would be
/// done, this can only be called after the request has finished.
vector< char > & getFullData() THROW_SPEC( exRequestUnfinished );
vector< char > & getFullData() ;
DataRequest(): hasAnyData( false ) {}
@ -344,7 +343,7 @@ public:
/// be stored. The whole operation is supposed to be fast, though some
/// dictionaries, the network ones particularly, may of course be slow.
virtual sptr< WordSearchRequest > prefixMatch( wstring const &,
unsigned long maxResults ) THROW_SPEC( std::exception )=0;
unsigned long maxResults ) =0;
/// Looks up a given word in the dictionary, aiming to find different forms
/// of the given word by allowing suffix variations. This means allowing words
@ -357,14 +356,14 @@ public:
virtual sptr< WordSearchRequest > stemmedMatch( wstring const &,
unsigned minLength,
unsigned maxSuffixVariation,
unsigned long maxResults ) THROW_SPEC( std::exception );
unsigned long maxResults ) ;
/// Finds known headwords for the given word, that is, the words for which
/// the given word is a synonym. If a dictionary can't perform this operation,
/// it should leave the default implementation which always returns an empty
/// result.
virtual sptr< WordSearchRequest > findHeadwordsForSynonym( wstring const & )
THROW_SPEC( std::exception );
;
/// For a given word, provides alternate writings of it which are to be looked
/// up alongside with it. Transliteration dictionaries implement this. The
@ -385,14 +384,14 @@ public:
vector< wstring > const & alts,
wstring const & context = wstring(),
bool ignoreDiacritics = false )
THROW_SPEC( std::exception )=0;
=0;
/// Loads contents of a resource named 'name' into the 'data' vector. This is
/// usually a picture file referenced in the article or something like that.
/// The default implementation always returns the non-existing resource
/// response.
virtual sptr< DataRequest > getResource( string const & /*name*/ )
THROW_SPEC( std::exception );
;
/// Returns a results of full-text search of given string similar getArticle().
virtual sptr< DataRequest > getSearchResults( QString const & searchString,
@ -480,6 +479,9 @@ bool needToRebuildIndex( vector< string > const & dictionaryFiles,
/// dictionaries.
QString generateRandomDictionaryId();
QMap< std::string, sptr< Dictionary::Class > >
dictToMap( std::vector< sptr< Dictionary::Class > > const & dicts );
}
#endif

View file

@ -211,7 +211,7 @@ void DictionaryBar::showContextMenu( QContextMenuEvent * event, bool extended )
{
QString command( editDictionaryCommand );
command.replace( "%GDDICT%", "\"" + dictFilename + "\"" );
if( !QProcess::startDetached( command ) )
if( !QProcess::startDetached( command ,QStringList()) )
QApplication::beep();
}

View file

@ -103,7 +103,7 @@ bool connectToServer( QTcpSocket & socket, QString const & url,
QString authCommand = QString( "AUTH " );
QString authString = msgId;
int pos = serverUrl.userInfo().indexOf( QRegExp( "[:;]" ) );
int pos = serverUrl.userInfo().indexOf( QRegularExpression( "[:;]" ) );
if( pos > 0 )
{
authCommand += serverUrl.userInfo().left( pos );
@ -200,11 +200,11 @@ public:
if( pos < 0 )
url = "dict://" + url;
databases = database_.split( QRegExp( "[ ,;]" ), Qt::SkipEmptyParts );
databases = database_.split( QRegularExpression( "[ ,;]" ), Qt::SkipEmptyParts );
if( databases.isEmpty() )
databases.append( "*" );
strategies = strategies_.split( QRegExp( "[ ,;]" ), Qt::SkipEmptyParts );
strategies = strategies_.split( QRegularExpression( "[ ,;]" ), Qt::SkipEmptyParts );
if( strategies.isEmpty() )
strategies.append( "prefix" );
}
@ -222,11 +222,11 @@ public:
{ return 0; }
virtual sptr< WordSearchRequest > prefixMatch( wstring const &,
unsigned long maxResults ) THROW_SPEC( std::exception );
unsigned long maxResults ) ;
virtual sptr< DataRequest > getArticle( wstring const &, vector< wstring > const & alts,
wstring const &, bool )
THROW_SPEC( std::exception );
;
virtual quint32 getLangFrom() const
{ return langId; }
@ -830,7 +830,7 @@ void DictServerArticleRequest::run()
while( it.hasNext() )
{
QRegularExpressionMatch match = it.next();
articleNewText += articleText.midRef( pos, match.capturedStart() - pos );
articleNewText += articleText.mid( pos, match.capturedStart() - pos );
pos = match.capturedEnd();
QString phonetic_text = match.captured( 1 );
@ -840,7 +840,7 @@ void DictServerArticleRequest::run()
}
if( pos )
{
articleNewText += articleText.midRef( pos );
articleNewText += articleText.mid( pos );
articleText = articleNewText;
articleNewText.clear();
}
@ -852,7 +852,7 @@ void DictServerArticleRequest::run()
while( it.hasNext() )
{
QRegularExpressionMatch match = it.next();
articleNewText += articleText.midRef( pos, match.capturedStart() - pos );
articleNewText += articleText.mid( pos, match.capturedStart() - pos );
pos = match.capturedEnd();
QString link = match.captured( 1 );
@ -866,7 +866,7 @@ void DictServerArticleRequest::run()
}
if( pos )
{
articleNewText += articleText.midRef( pos );
articleNewText += articleText.mid( pos );
articleText = articleNewText;
articleNewText.clear();
}
@ -918,7 +918,7 @@ void DictServerArticleRequest::cancel()
sptr< WordSearchRequest > DictServerDictionary::prefixMatch( wstring const & word,
unsigned long maxResults )
THROW_SPEC( std::exception )
{
(void) maxResults;
if ( word.size() > 80 )
@ -934,7 +934,7 @@ sptr< WordSearchRequest > DictServerDictionary::prefixMatch( wstring const & wor
sptr< DataRequest > DictServerDictionary::getArticle( wstring const & word,
vector< wstring > const &,
wstring const &, bool )
THROW_SPEC( std::exception )
{
if ( word.size() > 80 )
{
@ -949,7 +949,7 @@ sptr< DataRequest > DictServerDictionary::getArticle( wstring const & word,
} // Anonimuos namespace
vector< sptr< Dictionary::Class > > makeDictionaries( Config::DictServers const & servers )
THROW_SPEC( std::exception )
{
vector< sptr< Dictionary::Class > > result;

View file

@ -12,7 +12,7 @@ using std::string;
vector< sptr< Dictionary::Class > > makeDictionaries(
Config::DictServers const & servers )
THROW_SPEC( std::exception );
;
}

View file

@ -349,7 +349,9 @@ static enum DZ_ERRORS dict_read_header( const char *filename,
}
header->chunks = xmalloc( sizeof( header->chunks[0] )
* header->chunkCount );
if( header->chunks == 0 ) {
if( header->chunks == 0 )
{
fclose( str );
return DZ_ERR_NOMEMORY;
}

1
docs/_config.yml Normal file
View file

@ -0,0 +1 @@
theme: jekyll-theme-cayman

22
docs/index.md Normal file
View file

@ -0,0 +1,22 @@
## Welcome to GitHub Pages
This page serves as a release note page
### Releases
https://github.com/xiaoyifang/goldendict/releases
### version guideline
https://github.com/xiaoyifang/goldendict/wiki/Version--guideline
the first version has been named as 22.2.xxx.commit_hash.
22 means 2022 year.
2 means 2th month of the year.
### Support or Contact
Having trouble with Pages? Check out our [documentation](https://docs.github.com/categories/github-pages-basics/) or [contact support](https://support.github.com/contact) and well help you sort it out.

86
dsl.cc
View file

@ -217,10 +217,10 @@ public:
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getResource( string const & name )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString,
int searchMode, bool matchCase,
@ -580,7 +580,7 @@ void DslDictionary::loadArticle( uint32_t address,
if ( !articleBody )
{
// throw exCantReadFile( getDictionaryFilenames()[ 0 ] );
articleData = GD_NATIVE_TO_WS( L"\n\r\t" ) + gd::toWString( QString( "DICTZIP error: " ) + dict_error_str( dz ) );
articleData = U"\n\r\t" + gd::toWString( QString( "DICTZIP error: " ) + dict_error_str( dz ) );
}
else
{
@ -616,7 +616,7 @@ void DslDictionary::loadArticle( uint32_t address,
{
size_t begin = pos;
pos = articleData.find_first_of( GD_NATIVE_TO_WS( L"\n\r" ), begin );
pos = articleData.find_first_of( U"\n\r" , begin );
if ( pos == wstring::npos )
pos = articleData.size();
@ -741,7 +741,7 @@ void DslDictionary::loadArticle( uint32_t address,
if( insidedCard )
{
// Check for next insided headword
wstring::size_type hpos = articleData.find_first_of( GD_NATIVE_TO_WS( L"\n\r" ), pos );
wstring::size_type hpos = articleData.find_first_of( U"\n\r" , pos );
if ( hpos == wstring::npos )
hpos = articleData.size();
@ -820,13 +820,11 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
return result;
}
if ( node.tagName == GD_NATIVE_TO_WS( L"b" ) )
if( node.tagName == U"b" )
result += "<b class=\"dsl_b\">" + processNodeChildren( node ) + "</b>";
else
if ( node.tagName == GD_NATIVE_TO_WS( L"i" ) )
else if( node.tagName == U"i" )
result += "<i class=\"dsl_i\">" + processNodeChildren( node ) + "</i>";
else
if ( node.tagName == GD_NATIVE_TO_WS( L"u" ) )
else if( node.tagName == U"u" )
{
string nodeText = processNodeChildren( node );
@ -836,39 +834,32 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
result += "<span class=\"dsl_u\">" + nodeText + "</span>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"c" ) )
else if( node.tagName == U"c" )
{
result += "<font color=\"" + ( node.tagAttrs.size() ?
Html::escape( Utf8::encode( node.tagAttrs ) ) : string( "c_default_color" ) )
+ "\">" + processNodeChildren( node ) + "</font>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"*" ) )
else if( node.tagName == U"*" )
{
string id = "O" + getId().substr( 0, 7 ) + "_" +
QString::number( articleNom ).toStdString() +
"_opt_" + QString::number( optionalPartNom++ ).toStdString();
result += "<span class=\"dsl_opt\" id=\"" + id + "\">" + processNodeChildren( node ) + "</span>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"m" ) )
else if( node.tagName == U"m" )
result += "<div class=\"dsl_m\">" + processNodeChildren( node ) + "</div>";
else
if ( node.tagName.size() == 2 && node.tagName[ 0 ] == L'm' &&
iswdigit( node.tagName[ 1 ] ) )
result += "<div class=\"dsl_" + Utf8::encode( node.tagName ) + "\">" + processNodeChildren( node ) + "</div>";
else
if ( node.tagName == GD_NATIVE_TO_WS( L"trn" ) )
else if( node.tagName == U"trn" )
result += "<span class=\"dsl_trn\">" + processNodeChildren( node ) + "</span>";
else
if ( node.tagName == GD_NATIVE_TO_WS( L"ex" ) )
else if( node.tagName == U"ex" )
result += "<span class=\"dsl_ex\">" + processNodeChildren( node ) + "</span>";
else
if ( node.tagName == GD_NATIVE_TO_WS( L"com" ) )
else if( node.tagName == U"com" )
result += "<span class=\"dsl_com\">" + processNodeChildren( node ) + "</span>";
else
if ( node.tagName == GD_NATIVE_TO_WS( L"s" ) || node.tagName == GD_NATIVE_TO_WS( L"video" ) )
else if( node.tagName == U"s" || node.tagName == U"video" )
{
string filename = Filetype::simplifyString( Utf8::encode( node.renderAsText() ), false );
string n = resourceDir1 + FsEncoding::encode( filename );
@ -1013,8 +1004,7 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
+ "\">" + processNodeChildren( node ) + "</a>";
}
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"url" ) )
else if( node.tagName == U"url" )
{
string link = Html::escape( Filetype::simplifyString( Utf8::encode( node.renderAsText() ), false ) );
if( QUrl::fromEncoded( link.c_str() ).scheme().isEmpty() )
@ -1037,13 +1027,11 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
result += "<a class=\"dsl_url\" href=\"" + link +"\">" + processNodeChildren( node ) + "</a>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"!trs" ) )
else if( node.tagName == U"!trs" )
{
result += "<span class=\"dsl_trs\">" + processNodeChildren( node ) + "</span>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"p") )
else if( node.tagName == U"p" )
{
result += "<span class=\"dsl_p\"";
@ -1090,8 +1078,7 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
result += ">" + processNodeChildren( node ) + "</span>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"'" ) )
else if( node.tagName == U"'" )
{
// There are two ways to display the stress: by adding an accent sign or via font styles.
// We generate two spans, one with accented data and another one without it, so the
@ -1101,8 +1088,7 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
+ "<span class=\"dsl_stress_with_accent\">" + data + Utf8::encode( wstring( 1, 0x301 ) )
+ "</span></span>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"lang" ) )
else if( node.tagName == U"lang" )
{
result += "<span class=\"dsl_lang\"";
if( !node.tagAttrs.empty() )
@ -1135,8 +1121,7 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
}
result += ">" + processNodeChildren( node ) + "</span>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"ref" ) )
else if( node.tagName == U"ref" )
{
QUrl url;
@ -1158,8 +1143,7 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
result += string( "<a class=\"dsl_ref\" href=\"" ) + url.toEncoded().data() +"\">"
+ processNodeChildren( node ) + "</a>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"@" ) )
else if( node.tagName == U"@" )
{
// Special case - insided card header was not parsed
@ -1174,23 +1158,19 @@ string DslDictionary::nodeToHtml( ArticleDom::Node const & node )
result += string( "<a class=\"dsl_ref\" href=\"" ) + url.toEncoded().data() +"\">"
+ processNodeChildren( node ) + "</a>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"sub" ) )
else if( node.tagName == U"sub" )
{
result += "<sub>" + processNodeChildren( node ) + "</sub>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"sup" ) )
else if( node.tagName == U"sup" )
{
result += "<sup>" + processNodeChildren( node ) + "</sup>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"t" ) )
else if( node.tagName == U"t" )
{
result += "<span class=\"dsl_t\">" + processNodeChildren( node ) + "</span>";
}
else
if ( node.tagName == GD_NATIVE_TO_WS( L"br" ) )
else if( node.tagName == U"br" )
{
result += "<br />";
}
@ -1377,7 +1357,7 @@ void DslDictionary::getArticleText( uint32_t articleAddress, QString & headword,
{
size_t begin = pos;
pos = articleData.find_first_of( GD_NATIVE_TO_WS( L"\n\r" ), begin );
pos = articleData.find_first_of( U"\n\r" , begin );
if ( articleHeadword.empty() )
{
@ -1445,7 +1425,7 @@ void DslDictionary::getArticleText( uint32_t articleAddress, QString & headword,
if( insidedCard )
{
// Check for next insided headword
wstring::size_type hpos = articleData.find_first_of( GD_NATIVE_TO_WS( L"\n\r" ), pos );
wstring::size_type hpos = articleData.find_first_of( U"\n\r" , pos );
if ( hpos == wstring::npos )
hpos = articleData.size();
@ -1797,7 +1777,7 @@ sptr< Dictionary::DataRequest > DslDictionary::getArticle( wstring const & word,
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception )
{
return new DslArticleRequest( word, alts, *this, ignoreDiacritics );
}
@ -1983,7 +1963,7 @@ void DslResourceRequest::run()
}
sptr< Dictionary::DataRequest > DslDictionary::getResource( string const & name )
THROW_SPEC( std::exception )
{
return new DslResourceRequest( *this, name );
}
@ -2008,7 +1988,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
string const & indicesDir,
Dictionary::Initializing & initializing,
int maxPictureWidth, unsigned int maxHeadwordSize )
THROW_SPEC( std::exception )
{
vector< sptr< Dictionary::Class > > dictionaries;
@ -2075,7 +2055,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
try { // Here we intercept any errors during the read to save line at
// which the incident happened. We need alive scanner for that.
if ( scanner.getDictionaryName() == GD_NATIVE_TO_WS( L"Abbrev" ) )
if( scanner.getDictionaryName() == U"Abbrev" )
continue; // For now just skip abbreviations
// Building the index
@ -2163,7 +2143,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
if ( eof )
break;
curString.erase( 0, curString.find_first_not_of( GD_NATIVE_TO_WS( L" \t" ) ) );
curString.erase( 0, curString.find_first_not_of( U" \t" ) );
if ( keys.size() )
expandTildes( curString, keys.front() );

2
dsl.hh
View file

@ -17,7 +17,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
string const & indicesDir,
Dictionary::Initializing &,
int maxPictureWidth, unsigned int maxHeadwordSize )
THROW_SPEC( std::exception );
;
}

View file

@ -144,12 +144,10 @@ string findCodeForDslId( int id )
bool isAtSignFirst( wstring const & str )
{
// Test if '@' is first in string except spaces and dsl tags
QRegExp reg( "[ \\t]*(?:\\[[^\\]]+\\][ \\t]*)*@", Qt::CaseInsensitive, QRegExp::RegExp2 );
return reg.indexIn( gd::toQString( str ) ) == 0;
QRegularExpression reg( "[ \\t]*(?:\\[[^\\]]+\\][ \\t]*)*@", QRegularExpression::PatternOption::CaseInsensitiveOption);
return gd::toQString( str ).indexOf (reg) == 0;
}
/////////////// ArticleDom
wstring ArticleDom::Node::renderAsText( bool stripTrsTag ) const
@ -160,7 +158,7 @@ wstring ArticleDom::Node::renderAsText( bool stripTrsTag ) const
wstring result;
for( list< Node >::const_iterator i = begin(); i != end(); ++i )
if( !stripTrsTag || i->tagName != GD_NATIVE_TO_WS( L"!trs" ) )
if( !stripTrsTag || i->tagName != U"!trs" )
result += i->renderAsText( stripTrsTag );
return result;
@ -169,8 +167,7 @@ wstring ArticleDom::Node::renderAsText( bool stripTrsTag ) const
// Returns true if src == 'm' and dest is 'mX', where X is a digit
static inline bool checkM( wstring const & dest, wstring const & src )
{
return ( src == GD_NATIVE_TO_WS( L"m" ) && dest.size() == 2 &&
dest[ 0 ] == L'm' && iswdigit( dest[ 1 ] ) );
return ( src == U"m" && dest.size() == 2 && dest[ 0 ] == L'm' && iswdigit( dest[ 1 ] ) );
}
ArticleDom::ArticleDom( wstring const & str, string const & dictName,
@ -252,7 +249,7 @@ ArticleDom::ArticleDom( wstring const & str, string const & dictName,
wstring linkText = Folding::trimWhitespace( *entry );
ArticleDom nodeDom( linkText, dictName, headword_ );
Node link( Node::Tag(), GD_NATIVE_TO_WS( L"@" ), wstring() );
Node link( Node::Tag(), U"@" , wstring() );
for( Node::iterator n = nodeDom.root.begin(); n != nodeDom.root.end(); ++n )
link.push_back( *n );
@ -262,13 +259,13 @@ ArticleDom::ArticleDom( wstring const & str, string const & dictName,
{
root.push_back( link );
if( entry != allLinkEntries.end() ) // Add line break before next entry
root.push_back( Node( Node::Tag(), GD_NATIVE_TO_WS( L"br" ), wstring() ) );
root.push_back( Node( Node::Tag(), U"br" , wstring() ) );
}
else
{
stack.back()->push_back( link );
if( entry != allLinkEntries.end() )
stack.back()->push_back( Node( Node::Tag(), GD_NATIVE_TO_WS( L"br" ), wstring() ) );
stack.back()->push_back( Node( Node::Tag(), U"br" , wstring() ) );
}
}
@ -349,7 +346,7 @@ ArticleDom::ArticleDom( wstring const & str, string const & dictName,
}
// If the tag is [t], we update the transcriptionCount
if ( name == GD_NATIVE_TO_WS( L"t" ) )
if( name == U"t" )
{
if ( isClosing )
{
@ -361,7 +358,7 @@ ArticleDom::ArticleDom( wstring const & str, string const & dictName,
}
// If the tag is [s], we update the mediaCount
if ( name == GD_NATIVE_TO_WS( L"s" ) )
if( name == U"s" )
{
if ( isClosing )
{
@ -374,14 +371,13 @@ ArticleDom::ArticleDom( wstring const & str, string const & dictName,
if ( !isClosing )
{
if ( name == GD_NATIVE_TO_WS( L"m" ) ||
( name.size() == 2 && name[ 0 ] == L'm' && iswdigit( name[ 1 ] ) ) )
if( name == U"m" || ( name.size() == 2 && name[ 0 ] == L'm' && iswdigit( name[ 1 ] ) ) )
{
// Opening an 'mX' or 'm' tag closes any previous 'm' tag
closeTag( GD_NATIVE_TO_WS( L"m" ), stack, false );
closeTag( U"m" , stack, false );
}
openTag( name, attrs, stack );
if ( name == GD_NATIVE_TO_WS( L"br" ) )
if( name == U"br" )
{
// [br] tag don't have closing tag
closeTag( name, stack );
@ -465,7 +461,7 @@ ArticleDom::ArticleDom( wstring const & str, string const & dictName,
processUnsortedParts( linkText, true );
ArticleDom nodeDom( linkText, dictName, headword_ );
Node link( Node::Tag(), GD_NATIVE_TO_WS( L"ref" ), wstring() );
Node link( Node::Tag(), U"ref" , wstring() );
for( Node::iterator n = nodeDom.root.begin(); n != nodeDom.root.end(); ++n )
link.push_back( *n );
@ -640,7 +636,7 @@ void ArticleDom::openTag( wstring const & name,
{
list< Node > nodesToReopen;
if( name == GD_NATIVE_TO_WS( L"m" ) || checkM( name, GD_NATIVE_TO_WS( L"m" ) ) )
if( name == U"m" || checkM( name, U"m" ) )
{
// All tags above [m] tag will be closed and reopened after
// to avoid break this tag by closing some other tag.
@ -734,7 +730,7 @@ void ArticleDom::closeTag( wstring const & name,
nodesToReopen.push_back( Node( Node::Tag(), stack.back()->tagName,
stack.back()->tagAttrs ) );
if ( stack.back()->empty() && stack.back()->tagName != GD_NATIVE_TO_WS( L"br" ) )
if( stack.back()->empty() && stack.back()->tagName != U"br" )
{
// Empty nodes except [br] tag are deleted since they're no use
@ -780,7 +776,7 @@ void ArticleDom::closeTag( wstring const & name,
}
}
void ArticleDom::nextChar() THROW_SPEC( eot )
void ArticleDom::nextChar()
{
if ( !*stringPos )
throw eot();
@ -825,7 +821,7 @@ bool ArticleDom::atSignFirstInLine()
/////////////// DslScanner
DslScanner::DslScanner( string const & fileName ) THROW_SPEC( Ex, Iconv::Ex ):
DslScanner::DslScanner( string const & fileName ) :
encoding( Utf8::Windows1252 ), readBufferPtr( readBuffer ),
readBufferLeft( 0 ), linesRead( 0 )
{
@ -917,19 +913,15 @@ DslScanner::DslScanner( string const & fileName ) THROW_SPEC( Ex, Iconv::Ex ):
bool isLangTo = false;
bool isSoundDict = false;
if ( !str.compare( 0, 5, GD_NATIVE_TO_WS( L"#NAME" ), 5 ) )
if( !str.compare( 0, 5, U"#NAME" , 5 ) )
isName = true;
else
if ( !str.compare( 0, 15, GD_NATIVE_TO_WS( L"#INDEX_LANGUAGE" ), 15 ) )
else if( !str.compare( 0, 15, U"#INDEX_LANGUAGE" , 15 ) )
isLangFrom = true;
else
if ( !str.compare( 0, 18, GD_NATIVE_TO_WS( L"#CONTENTS_LANGUAGE" ), 18 ) )
else if( !str.compare( 0, 18, U"#CONTENTS_LANGUAGE" , 18 ) )
isLangTo = true;
else
if ( !str.compare( 0, 17, GD_NATIVE_TO_WS( L"#SOUND_DICTIONARY" ), 17 ) )
else if( !str.compare( 0, 17, U"#SOUND_DICTIONARY" , 17 ) )
isSoundDict = true;
else
if ( str.compare( 0, 17, GD_NATIVE_TO_WS( L"#SOURCE_CODE_PAGE" ), 17 ) )
else if( str.compare( 0, 17, U"#SOURCE_CODE_PAGE" , 17 ) )
continue;
// Locate the argument
@ -962,14 +954,11 @@ DslScanner::DslScanner( string const & fileName ) THROW_SPEC( Ex, Iconv::Ex ):
// We don't need that!
GD_FDPRINTF( stderr, "Warning: encoding was specified in a Unicode file, ignoring.\n" );
}
else
if ( !wcscasecmp( arg.c_str(), GD_NATIVE_TO_WS( L"Latin" ) ) )
else if( !arg.compare( U"Latin" ) )
encoding = Utf8::Windows1252;
else
if ( !wcscasecmp( arg.c_str(), GD_NATIVE_TO_WS( L"Cyrillic" ) ) )
else if( !arg.compare( U"Cyrillic" ) )
encoding = Utf8::Windows1251;
else
if ( !wcscasecmp( arg.c_str(), GD_NATIVE_TO_WS( L"EasternEuropean" ) ) )
else if( !arg.compare( U"EasternEuropean" ) )
encoding = Utf8::Windows1250;
else
{
@ -995,8 +984,7 @@ DslScanner::~DslScanner() throw()
gzclose( f );
}
bool DslScanner::readNextLine( wstring & out, size_t & offset, bool only_head_word ) THROW_SPEC( Ex,
Iconv::Ex )
bool DslScanner::readNextLine( wstring & out, size_t & offset, bool only_head_word )
{
offset = (size_t)( gztell( f ) - readBufferLeft/*+pos*/ );
@ -1042,7 +1030,7 @@ bool DslScanner::readNextLine( wstring & out, size_t & offset, bool only_head_wo
#ifdef __WIN32
out=line.toStdU32String();
#else
out=line.toStdWString();
out=line.toStdU32String();
#endif
return true;
@ -1050,7 +1038,7 @@ bool DslScanner::readNextLine( wstring & out, size_t & offset, bool only_head_wo
}
bool DslScanner::readNextLineWithoutComments( wstring & out, size_t & offset , bool only_headword)
THROW_SPEC( Ex, Iconv::Ex )
{
wstring str;
bool commentToNextLine = false;
@ -1163,6 +1151,12 @@ void expandOptionalParts( wstring & str, list< wstring > * result,
list< wstring > * headwords;
headwords = inside_recurse ? result : &expanded;
//if str is too long ,it can never be headwords.
//todo?
if( str.size() > 100 )
{
return;
}
for( ; x < str.size(); )
{
wchar ch = str[ x ];
@ -1257,8 +1251,8 @@ void expandOptionalParts( wstring & str, list< wstring > * result,
}
}
static const wstring openBraces( GD_NATIVE_TO_WS( L"{{" ) );
static const wstring closeBraces( GD_NATIVE_TO_WS( L"}}" ) );
static const wstring openBraces( U"{{" );
static const wstring closeBraces( U"}}" );
void stripComments( wstring & str, bool & nextLine )
{
@ -1357,11 +1351,11 @@ namespace
quint32 dslLanguageToId( wstring const & name )
{
static wstring newSp( GD_NATIVE_TO_WS( L"newspelling" ) );
static wstring st( GD_NATIVE_TO_WS( L"standard" ) );
static wstring ms( GD_NATIVE_TO_WS( L"modernsort" ) );
static wstring ts( GD_NATIVE_TO_WS( L"traditionalsort" ) );
static wstring prc( GD_NATIVE_TO_WS( L"prc" ) );
static wstring newSp( U"newspelling" );
static wstring st( U"standard" );
static wstring ms( U"modernsort" );
static wstring ts( U"traditionalsort" );
static wstring prc( U"prc" );
// Any of those endings are to be removed

View file

@ -10,7 +10,11 @@
#include <zlib.h>
#include "dictionary.hh"
#include "iconv.hh"
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QTextCodec>
#else
#include <QTextCodec>
#endif
#include <QByteArray>
#include "utf8.hh"
@ -91,7 +95,7 @@ private:
unsigned transcriptionCount; // >0 = inside a [t] tag
unsigned mediaCount; // >0 = inside a [s] tag
void nextChar() THROW_SPEC( eot );
void nextChar() ;
/// Information for diagnostic purposes
string dictionaryName;
@ -125,7 +129,7 @@ public:
DEF_EX( exUnknownCodePage, "The .dsl file specified an unknown code page", Ex )
DEF_EX( exEncodingError, "Encoding error", Ex ) // Should never happen really
DslScanner( string const & fileName ) THROW_SPEC( Ex, Iconv::Ex );
DslScanner( string const & fileName ) ;
~DslScanner() throw();
/// Returns the detected encoding of this file.
@ -154,10 +158,10 @@ public:
/// If end of file is reached, false is returned.
/// Reading begins from the first line after the headers (ones which start
/// with #).
bool readNextLine( wstring &, size_t & offset, bool only_head_word = false ) THROW_SPEC( Ex, Iconv::Ex );
bool readNextLine( wstring &, size_t & offset, bool only_head_word = false ) ;
/// Similar readNextLine but strip all DSL comments {{...}}
bool readNextLineWithoutComments( wstring &, size_t & offset, bool only_headword = false ) THROW_SPEC( Ex, Iconv::Ex );
bool readNextLineWithoutComments( wstring &, size_t & offset, bool only_headword = false ) ;
/// Returns the number of lines read so far from the file.
unsigned getLinesRead() const

View file

@ -11,17 +11,19 @@ using std::vector;
EditDictionaries::EditDictionaries( QWidget * parent, Config::Class & cfg_,
vector< sptr< Dictionary::Class > > & dictionaries_,
QMap<std::string, sptr< Dictionary::Class > > & dictMap_,
Instances::Groups & groupInstances_,
QNetworkAccessManager & dictNetMgr_ ):
QDialog( parent, Qt::WindowSystemMenuHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint ),
cfg( cfg_ ),
dictionaries( dictionaries_ ),
dictMap(dictMap_),
groupInstances( groupInstances_ ),
dictNetMgr( dictNetMgr_ ),
origCfg( cfg ),
sources( this, cfg ),
orderAndProps( new OrderAndProps( this, cfg.dictionaryOrder, cfg.inactiveDictionaries,
dictionaries ) ),
dictionaries, dictMap ) ),
groups( new Groups( this, dictionaries, cfg.groups, orderAndProps->getCurrentDictionaryOrder() ) ),
dictionariesChanged( false ),
groupsChanged( false ),
@ -73,8 +75,12 @@ EditDictionaries::EditDictionaries( QWidget * parent, Config::Class & cfg_,
void EditDictionaries::editGroup( unsigned id )
{
ui.tabs->setTabVisible( 0, false );
if ( id == Instances::Group::AllGroupId )
{
ui.tabs->setCurrentIndex( 1 );
}
else
{
ui.tabs->setCurrentIndex( 2 );
@ -207,15 +213,14 @@ void EditDictionaries::acceptChangedSources( bool rebuildGroups )
groupInstances.clear(); // Those hold pointers to dictionaries, we need to
// free them.
ui.tabs->setUpdatesEnabled( false );
ui.tabs->removeTab( 1 );
ui.tabs->removeTab( 1 );
groups.reset();
orderAndProps.reset();
loadDictionaries( this, true, cfg, dictionaries, dictNetMgr );
dictMap = Dictionary::dictToMap(dictionaries);
// If no changes to groups were made, update the original data
bool noGroupEdits = ( origCfg.groups == savedGroups );
@ -240,13 +245,15 @@ void EditDictionaries::acceptChangedSources( bool rebuildGroups )
if ( rebuildGroups )
{
orderAndProps = new OrderAndProps( this, savedOrder, savedInactive, dictionaries );
orderAndProps = new OrderAndProps( this, savedOrder, savedInactive, dictionaries, dictMap );
groups = new Groups( this, dictionaries, savedGroups, orderAndProps->getCurrentDictionaryOrder() );
ui.tabs->removeTab( 1 );
ui.tabs->removeTab( 1 );
ui.tabs->insertTab( 1, orderAndProps.get(), QIcon(":/icons/book.svg"), tr( "&Dictionaries" ) );
groups = new Groups( this, dictionaries, savedGroups, orderAndProps->getCurrentDictionaryOrder() );
ui.tabs->insertTab( 2, groups.get(), QIcon(":/icons/bookcase.svg"), tr( "&Groups" ) );
ui.tabs->setUpdatesEnabled( true );
if ( noGroupEdits )
origCfg.groups = groups->getGroups();
@ -257,6 +264,8 @@ void EditDictionaries::acceptChangedSources( bool rebuildGroups )
if ( noInactiveEdits )
origCfg.inactiveDictionaries = orderAndProps->getCurrentInactiveDictionaries();
}
ui.tabs->setUpdatesEnabled( true );
}
void EditDictionaries::helpRequested()

View file

@ -23,6 +23,7 @@ public:
EditDictionaries( QWidget * parent, Config::Class & cfg,
std::vector< sptr< Dictionary::Class > > & dictionaries,
QMap<std::string, sptr< Dictionary::Class > > & dictMap_,
Instances::Groups & groupInstances, // We only clear those on rescan
QNetworkAccessManager & dictNetMgr );
@ -73,6 +74,7 @@ private:
Config::Class & cfg;
std::vector< sptr< Dictionary::Class > > & dictionaries;
QMap<std::string, sptr< Dictionary::Class > > & dictMap;
Instances::Groups & groupInstances;
QNetworkAccessManager & dictNetMgr;

View file

@ -120,10 +120,10 @@ public:
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getResource( string const & name )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString,
int searchMode, bool matchCase,
@ -153,13 +153,13 @@ public:
virtual sptr< Dictionary::WordSearchRequest > prefixMatch( wstring const &,
unsigned long )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::WordSearchRequest > stemmedMatch( wstring const &,
unsigned minLength,
unsigned maxSuffixVariation,
unsigned long maxResults )
THROW_SPEC( std::exception );
;
protected:
@ -657,7 +657,7 @@ sptr< Dictionary::DataRequest > EpwingDictionary::getArticle( wstring const & wo
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception )
{
return new EpwingArticleRequest( word, alts, *this, ignoreDiacritics );
}
@ -785,7 +785,7 @@ void EpwingResourceRequest::run()
}
sptr< Dictionary::DataRequest > EpwingDictionary::getResource( string const & name )
THROW_SPEC( std::exception )
{
return new EpwingResourceRequest( *this, name );
}
@ -932,7 +932,7 @@ void EpwingWordSearchRequest::findMatches()
sptr< Dictionary::WordSearchRequest > EpwingDictionary::prefixMatch(
wstring const & str, unsigned long maxResults )
THROW_SPEC( std::exception )
{
return new EpwingWordSearchRequest( *this, str, 0, -1, true, maxResults );
}
@ -940,7 +940,7 @@ sptr< Dictionary::WordSearchRequest > EpwingDictionary::prefixMatch(
sptr< Dictionary::WordSearchRequest > EpwingDictionary::stemmedMatch(
wstring const & str, unsigned minLength, unsigned maxSuffixVariation,
unsigned long maxResults )
THROW_SPEC( std::exception )
{
return new EpwingWordSearchRequest( *this, str, minLength, (int)maxSuffixVariation,
false, maxResults );
@ -952,14 +952,12 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
Dictionary::Initializing & initializing )
THROW_SPEC( std::exception )
{
vector< sptr< Dictionary::Class > > dictionaries;
vector< string > dictFiles;
QByteArray catName;
catName += QDir::separator();
catName += "catalogs";
QByteArray catName = QString("%1catalogs").arg(QDir::separator()).toUtf8();
for( vector< string >::const_iterator i = fileNames.begin(); i != fileNames.end();
++i )

View file

@ -13,7 +13,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
Dictionary::Initializing & )
THROW_SPEC( std::exception );
;
}
#endif // __EPWING_HH__INCLUDED__

View file

@ -13,6 +13,9 @@
#include "wstring_qt.hh"
#include "folding.hh"
#include "epwing_charmap.hh"
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat>
#endif
#if defined( Q_OS_WIN32 ) || defined( Q_OS_MAC )
#define _FILE_OFFSET_BITS 64
@ -550,7 +553,8 @@ bool EpwingBook::setSubBook( int book_nom )
if( f.open( QFile::ReadOnly | QFile::Text ) )
{
QTextStream ts( &f );
ts.setCodec( "UTF-8" );
//todo?
// ts.setCodec( "UTF-8" );
QString line = ts.readLine();
while( !line.isEmpty() )
@ -853,7 +857,7 @@ bool EpwingBook::getNextHeadword( EpwingHeadword & head )
{
EB_Position pos;
QRegExp badLinks( "#(v|n)\\d" );
QRegularExpression badLinks( "#(v|n)\\d" );
// At first we check references queue
while( !LinksQueue.isEmpty() )
@ -1031,7 +1035,8 @@ void EpwingBook::fixHeadword( QString & headword )
return;
QString fixed = headword;
fixed.remove( QRegExp( "/[^/]+/", Qt::CaseSensitive ) );
QRegularExpression leadingSlashRx( "/[^/]+/" );
fixed.remove(leadingSlashRx );
if( isHeadwordCorrect( fixed ) )
{
@ -1202,8 +1207,8 @@ void EpwingBook::finalizeText( QString & text )
// Replace references
int pos = 0;
QRegExp reg1( "<R[^<]*>" );
QRegExp reg2( "</R[^<]*>" );
QRegularExpression reg1( "<R[^<]*>" );
QRegularExpression reg2( "</R[^<]*>" );
EContainer cont( this, true );
@ -1239,13 +1244,14 @@ void EpwingBook::finalizeText( QString & text )
QString link = "<a href=\"" + url.toEncoded() + "\">";
text.replace( reg1.cap(), link );
//todo ? iterate cap ,or replace as a whole?
text.replace( reg1, link );
pos = text.indexOf( reg2, pos );
if( pos < 0 )
break;
text.replace( reg2.cap(), "</a>" );
text.replace( reg2, "</a>" );
}
}
@ -1732,8 +1738,7 @@ QByteArray EpwingBook::handleReference( EB_Hook_Code code, const unsigned int *
if( refOpenCount > refCloseCount )
return QByteArray();
QString str;
str.sprintf( "<R%i>", refOpenCount );
QString str=QString( "<R%1>").arg( refOpenCount );
refOpenCount += 1;
return str.toUtf8();
}
@ -1747,7 +1752,7 @@ QByteArray EpwingBook::handleReference( EB_Hook_Code code, const unsigned int *
refOffsets.append( argv[ 2 ] );
QString str;
str.sprintf( "</R%i>", refCloseCount );
str.asprintf( "</R%i>", refCloseCount );
refCloseCount += 1;
return str.toUtf8();

View file

@ -12,7 +12,11 @@
#include "mutex.hh"
#include <QString>
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QTextCodec>
#else
#include <QTextCodec>
#endif
#include <QMap>
#include <QVector>
#include <vector>

View file

@ -19,9 +19,9 @@ QByteArray EpwingCharmap::mapToUtf8( QString const & code )
return QByteArray();
}
void EpwingCharmap::addEntry( QString const & code, QChar ch )
void EpwingCharmap::addEntry( QString const & code, int ch )
{
charMap[ code ] = ch;
charMap[ code ] = QChar(ch);
}
EpwingCharmap::EpwingCharmap()

View file

@ -20,7 +20,7 @@ public:
private:
EpwingCharmap();
void addEntry( QString const & code, QChar ch );
void addEntry( QString const & code, int ch );
QMap< QString, QChar > charMap;
};

View file

@ -10,7 +10,7 @@
ExternalViewer::ExternalViewer( const char * data, int size,
QString const & extension, QString const & viewerCmdLine_,
QObject * parent)
THROW_SPEC( exCantCreateTempFile ):
:
QObject( parent ),
tempFile( QDir::temp().filePath( QString( "gd-XXXXXXXX." ) + extension ) ),
viewer( this ),
@ -31,7 +31,7 @@ ExternalViewer::ExternalViewer( const char * data, int size,
GD_DPRINTF( "%s\n", tempFile.fileName().toLocal8Bit().data() );
}
void ExternalViewer::start() THROW_SPEC( exCantRunViewer )
void ExternalViewer::start()
{
connect( &viewer, SIGNAL( finished( int, QProcess::ExitStatus ) ),
this, SLOT( deleteLater() ) );

View file

@ -8,7 +8,6 @@
#include <QTemporaryFile>
#include <QProcess>
#include "ex.hh"
#include "cpp_features.hh"
/// An external viewer, opens resources in other programs
class ExternalViewer: public QObject
@ -29,11 +28,11 @@ public:
ExternalViewer( const char * data, int size,
QString const & extension, QString const & viewerCmdLine,
QObject * parent = 0 )
THROW_SPEC( exCantCreateTempFile );
;
// Once this is called, the object will be deleted when it's done, even if
// the function throws.
void start() THROW_SPEC( exCantRunViewer );
void start() ;
/// If the external process is running, requests its termination and returns
/// false - expect the QObject::destroyed() signal to be emitted soon.

View file

@ -110,14 +110,12 @@ void ExtLineEdit::updateButtonPositions()
iconPos = (iconPos == Left ? Right : Left);
if (iconPos == ExtLineEdit::Right) {
int right;
getTextMargins(0, 0, &right, 0);
const int iconoffset = right + 4;
QMargins qm=textMargins();
const int iconoffset = qm.right() + 4;
iconButtons[i]->setGeometry(contentRect.adjusted(width() - iconoffset, 0, 0, 0));
} else {
int left;
getTextMargins(&left, 0, 0, 0);
const int iconoffset = left + 4;
QMargins qm=textMargins();
const int iconoffset = qm.left() + 4;
iconButtons[i]->setGeometry(contentRect.adjusted(0, 0, -width() + iconoffset, 0));
}
}

View file

@ -907,7 +907,8 @@ void FavoritesModel::removeItemsForIndexes( const QModelIndexList & idxList )
for( int i = lowestLevel; i >= 0; i-- )
{
QModelIndexList idxSublist = itemsToDelete[ i ];
std::sort( idxSublist.begin(), idxSublist.end(), qGreater< QModelIndex >() );
// std::greater does not work as operator < not implemented
std::sort( idxSublist.begin(), idxSublist.end(), std::not2( std::less< QModelIndex >() ) );
it = idxSublist.begin();
for( ; it != idxSublist.end(); ++it )

View file

@ -52,9 +52,6 @@ AudioService & AudioService::instance()
AudioService::AudioService()
{
#if LIBAVFORMAT_VERSION_MAJOR < 58 || ( LIBAVFORMAT_VERSION_MAJOR == 58 && LIBAVFORMAT_VERSION_MINOR < 9 )
av_register_all();
#endif
ao_initialize();
}
@ -94,7 +91,11 @@ struct DecoderContext
QByteArray audioData_;
QDataStream audioDataStream_;
AVFormatContext * formatContext_;
#if LIBAVCODEC_VERSION_MAJOR < 59
AVCodec * codec_;
#else
const AVCodec * codec_;
#endif
AVCodecContext * codecContext_;
AVIOContext * avioContext_;
AVStream * audioStream_;
@ -151,11 +152,8 @@ bool DecoderContext::openCodec( QString & errorString )
return false;
}
#if LIBAVCODEC_VERSION_MAJOR < 56 || ( LIBAVCODEC_VERSION_MAJOR == 56 && LIBAVCODEC_VERSION_MINOR < 56 )
unsigned char * avioBuffer = ( unsigned char * )av_malloc( kBufferSize + FF_INPUT_BUFFER_PADDING_SIZE );
#else
unsigned char * avioBuffer = ( unsigned char * )av_malloc( kBufferSize + AV_INPUT_BUFFER_PADDING_SIZE );
#endif
if ( !avioBuffer )
{
errorString = QObject::tr( "av_malloc() failed." );
@ -198,11 +196,7 @@ bool DecoderContext::openCodec( QString & errorString )
// Find audio stream, use the first audio stream if available
for ( unsigned i = 0; i < formatContext_->nb_streams; i++ )
{
#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 33 )
if ( formatContext_->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO )
#else
if ( formatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO )
#endif
{
audioStream_ = formatContext_->streams[i];
break;
@ -214,15 +208,6 @@ bool DecoderContext::openCodec( QString & errorString )
return false;
}
#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 33 )
codecContext_ = audioStream_->codec;
codec_ = avcodec_find_decoder( codecContext_->codec_id );
if ( !codec_ )
{
errorString = QObject::tr( "Codec [id: %1] not found." ).arg( codecContext_->codec_id );
return false;
}
#else
codec_ = avcodec_find_decoder( audioStream_->codecpar->codec_id );
if ( !codec_ )
{
@ -236,7 +221,6 @@ bool DecoderContext::openCodec( QString & errorString )
return false;
}
avcodec_parameters_to_context( codecContext_, audioStream_->codecpar );
#endif
ret = avcodec_open2( codecContext_, codec_, NULL );
if ( ret < 0 )
@ -313,9 +297,7 @@ void DecoderContext::closeCodec()
{
audioStream_->discard = AVDISCARD_ALL;
avcodec_close( codecContext_ );
#if LIBAVCODEC_VERSION_MAJOR > 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR >= 33 )
avcodec_free_context( &codecContext_ );
#endif
}
avformat_close_input( &formatContext_ );
@ -397,11 +379,7 @@ void DecoderContext::closeOutputDevice()
bool DecoderContext::play( QString & errorString )
{
#if LIBAVCODEC_VERSION_MAJOR < 55 || ( LIBAVCODEC_VERSION_MAJOR == 55 && LIBAVCODEC_VERSION_MINOR < 28 )
AVFrame * frame = avcodec_alloc_frame();
#else
AVFrame * frame = av_frame_alloc();
#endif
if ( !frame )
{
errorString = QObject::tr( "avcodec_alloc_frame() failed." );
@ -417,22 +395,6 @@ bool DecoderContext::play( QString & errorString )
if ( packet.stream_index == audioStream_->index )
{
AVPacket pack = packet;
#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 37 )
int gotFrame = 0;
do
{
int len = avcodec_decode_audio4( codecContext_, frame, &gotFrame, &pack );
if ( !Utils::AtomicInt::loadAcquire( isCancelled_ ) && gotFrame )
{
playFrame( frame );
}
if( len <= 0 || Utils::AtomicInt::loadAcquire( isCancelled_ ) )
break;
pack.size -= len;
pack.data += len;
}
while( pack.size > 0 );
#else
int ret = avcodec_send_packet( codecContext_, &pack );
/* read all the output frames (in general there may be any number of them) */
while( ret >= 0 )
@ -444,30 +406,13 @@ bool DecoderContext::play( QString & errorString )
playFrame( frame );
}
#endif
}
// av_free_packet() must be called after each call to av_read_frame()
#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 7 )
av_free_packet( &packet );
#else
av_packet_unref( &packet );
#endif
}
#if LIBAVCODEC_VERSION_MAJOR < 57 || ( LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR < 37 )
if ( !Utils::AtomicInt::loadAcquire( isCancelled_ ) &&
codecContext_->codec->capabilities & CODEC_CAP_DELAY )
{
av_init_packet( &packet );
int gotFrame = 0;
while ( avcodec_decode_audio4( codecContext_, frame, &gotFrame, &packet ) >= 0 && gotFrame )
{
if ( Utils::AtomicInt::loadAcquire( isCancelled_ ) )
break;
playFrame( frame );
av_packet_unref( &packet );
}
}
#else
/* flush the decoder */
av_init_packet( &packet );
packet.data = NULL;
@ -480,28 +425,10 @@ bool DecoderContext::play( QString & errorString )
break;
playFrame( frame );
}
#endif
#if LIBAVCODEC_VERSION_MAJOR < 54
av_free( frame );
#elif LIBAVCODEC_VERSION_MAJOR < 55 || ( LIBAVCODEC_VERSION_MAJOR == 55 && LIBAVCODEC_VERSION_MINOR < 28 )
avcodec_free_frame( &frame );
#else
av_frame_free( &frame );
#endif
return true;
}
static inline int32_t toInt32( double v )
{
if ( v >= 1.0 )
return 0x7fffffffL;
else if ( v <= -1.0 )
return 0x80000000L;
return floor( v * 2147483648.0 );
}
bool DecoderContext::normalizeAudio( AVFrame * frame, vector<char> & samples )
{
int lineSize = 0;

38
file.cc
View file

@ -88,7 +88,7 @@ bool exists( char const * filename ) throw()
#endif
}
void Class::open( char const * filename, char const * mode ) THROW_SPEC( exCantOpen )
void Class::open( char const * filename, char const * mode )
{
QFile::OpenMode openMode = QIODevice::Text;
const char * pch = mode;
@ -118,19 +118,19 @@ void Class::open( char const * filename, char const * mode ) THROW_SPEC( exCantO
throw exCantOpen( std::string( filename ) + ": " + f.errorString().toUtf8().data() );
}
Class::Class( char const * filename, char const * mode ) THROW_SPEC( exCantOpen ):
Class::Class( char const * filename, char const * mode ) :
writeBuffer( 0 )
{
open( filename, mode );
}
Class::Class( std::string const & filename, char const * mode )
THROW_SPEC( exCantOpen ): writeBuffer( 0 )
: writeBuffer( 0 )
{
open( filename.c_str(), mode );
}
void Class::read( void * buf, qint64 size ) THROW_SPEC( exReadError, exWriteError )
void Class::read( void * buf, qint64 size )
{
if ( !size )
return;
@ -144,7 +144,7 @@ void Class::read( void * buf, qint64 size ) THROW_SPEC( exReadError, exWriteErro
throw exReadError();
}
size_t Class::readRecords( void * buf, qint64 size, size_t count ) THROW_SPEC( exWriteError )
size_t Class::readRecords( void * buf, qint64 size, size_t count )
{
if ( writeBuffer )
flushWriteBuffer();
@ -153,7 +153,7 @@ size_t Class::readRecords( void * buf, qint64 size, size_t count ) THROW_SPEC( e
return result < 0 ? result : result / size;
}
void Class::write( void const * buf, qint64 size ) THROW_SPEC( exWriteError, exAllocation )
void Class::write( void const * buf, qint64 size )
{
if ( !size )
return;
@ -201,7 +201,7 @@ void Class::write( void const * buf, qint64 size ) THROW_SPEC( exWriteError, exA
}
size_t Class::writeRecords( void const * buf, qint64 size, size_t count )
THROW_SPEC( exWriteError )
{
flushWriteBuffer();
@ -210,7 +210,7 @@ size_t Class::writeRecords( void const * buf, qint64 size, size_t count )
}
char * Class::gets( char * s, int size, bool stripNl )
THROW_SPEC( exWriteError )
{
if ( writeBuffer )
flushWriteBuffer();
@ -237,7 +237,7 @@ char * Class::gets( char * s, int size, bool stripNl )
return result;
}
std::string Class::gets( bool stripNl ) THROW_SPEC( exReadError, exWriteError )
std::string Class::gets( bool stripNl )
{
char buf[ 1024 ];
@ -247,7 +247,7 @@ std::string Class::gets( bool stripNl ) THROW_SPEC( exReadError, exWriteError )
return std::string( buf );
}
void Class::seek( qint64 offset ) THROW_SPEC( exSeekError, exWriteError )
void Class::seek( qint64 offset )
{
if ( writeBuffer )
flushWriteBuffer();
@ -256,7 +256,7 @@ void Class::seek( qint64 offset ) THROW_SPEC( exSeekError, exWriteError )
throw exSeekError();
}
void Class::seekCur( qint64 offset ) THROW_SPEC( exSeekError, exWriteError )
void Class::seekCur( qint64 offset )
{
if ( writeBuffer )
flushWriteBuffer();
@ -265,7 +265,7 @@ void Class::seekCur( qint64 offset ) THROW_SPEC( exSeekError, exWriteError )
throw exSeekError();
}
void Class::seekEnd( qint64 offset ) THROW_SPEC( exSeekError, exWriteError )
void Class::seekEnd( qint64 offset )
{
if ( writeBuffer )
flushWriteBuffer();
@ -274,12 +274,12 @@ void Class::seekEnd( qint64 offset ) THROW_SPEC( exSeekError, exWriteError )
throw exSeekError();
}
void Class::rewind() THROW_SPEC( exSeekError, exWriteError )
void Class::rewind()
{
seek( 0 );
}
qint64 Class::tell() THROW_SPEC( exSeekError )
qint64 Class::tell()
{
qint64 result = f.pos();
@ -292,7 +292,7 @@ qint64 Class::tell() THROW_SPEC( exSeekError )
return result;
}
bool Class::eof() THROW_SPEC( exWriteError )
bool Class::eof()
{
if ( writeBuffer )
flushWriteBuffer();
@ -300,14 +300,14 @@ bool Class::eof() THROW_SPEC( exWriteError )
return f.atEnd();
}
QFile & Class::file() THROW_SPEC( exWriteError )
QFile & Class::file()
{
flushWriteBuffer();
return f;
}
void Class::close() THROW_SPEC( exWriteError )
void Class::close()
{
releaseWriteBuffer();
f.close();
@ -328,7 +328,7 @@ Class::~Class() throw()
}
}
void Class::flushWriteBuffer() THROW_SPEC( exWriteError )
void Class::flushWriteBuffer()
{
if ( writeBuffer && writeBufferLeft != WriteBufferSize )
{
@ -341,7 +341,7 @@ void Class::flushWriteBuffer() THROW_SPEC( exWriteError )
}
}
void Class::releaseWriteBuffer() THROW_SPEC( exWriteError )
void Class::releaseWriteBuffer()
{
flushWriteBuffer();

45
file.hh
View file

@ -8,7 +8,6 @@
#include <string>
#include <vector>
#include <QFile>
#include "cpp_features.hh"
#include "ex.hh"
/// A simple wrapper over FILE * operations with added write-buffering,
@ -42,29 +41,29 @@ class Class
char * writeBuffer;
qint64 writeBufferLeft;
void open( char const * filename, char const * mode ) THROW_SPEC( exCantOpen );
void open( char const * filename, char const * mode ) ;
public:
Class( char const * filename, char const * mode ) THROW_SPEC( exCantOpen );
Class( char const * filename, char const * mode ) ;
Class( std::string const & filename, char const * mode ) THROW_SPEC( exCantOpen );
Class( std::string const & filename, char const * mode ) ;
/// Reads the number of bytes to the buffer, throws an error if it
/// failed to fill the whole buffer (short read, i/o error etc).
void read( void * buf, qint64 size ) THROW_SPEC( exReadError, exWriteError );
void read( void * buf, qint64 size ) ;
template< typename T >
void read( T & value ) THROW_SPEC( exReadError, exWriteError )
void read( T & value )
{ read( &value, sizeof( value ) ); }
template< typename T >
T read() THROW_SPEC( exReadError, exWriteError )
T read()
{ T value; read( value ); return value; }
/// Attempts reading at most 'count' records sized 'size'. Returns
/// the number of records it managed to read, up to 'count'.
size_t readRecords( void * buf, qint64 size, size_t count ) THROW_SPEC( exWriteError );
size_t readRecords( void * buf, qint64 size, size_t count ) ;
/// Writes the number of bytes from the buffer, throws an error if it
/// failed to write the whole buffer (short write, i/o error etc).
@ -72,10 +71,10 @@ public:
/// end up on disk immediately, or a short write may occur later
/// than it really did. If you don't want write buffering, use
/// writeRecords() function instead.
void write( void const * buf, qint64 size ) THROW_SPEC( exWriteError, exAllocation );
void write( void const * buf, qint64 size ) ;
template< typename T >
void write( T const & value ) THROW_SPEC( exWriteError )
void write( T const & value )
{ write( &value, sizeof( value ) ); }
/// Attempts writing at most 'count' records sized 'size'. Returns
@ -83,46 +82,46 @@ public:
/// This function does not employ buffering, but flushes the buffer if it
/// was used before.
size_t writeRecords( void const * buf, qint64 size, size_t count )
THROW_SPEC( exWriteError );
;
/// Reads a string from the file. Unlike the normal fgets(), this one
/// can strip the trailing newline character, if this was requested.
/// Returns either s or 0 if no characters were read.
char * gets( char * s, int size, bool stripNl = false ) THROW_SPEC( exWriteError );
char * gets( char * s, int size, bool stripNl = false ) ;
/// Like the above, but uses its own local internal buffer (1024 bytes
/// currently), and strips newlines by default.
std::string gets( bool stripNl = true ) THROW_SPEC( exReadError, exWriteError );
std::string gets( bool stripNl = true ) ;
/// Seeks in the file, relative to its beginning.
void seek( qint64 offset ) THROW_SPEC( exSeekError, exWriteError );
void seek( qint64 offset ) ;
/// Seeks in the file, relative to the current position.
void seekCur( qint64 offset ) THROW_SPEC( exSeekError, exWriteError );
void seekCur( qint64 offset ) ;
/// Seeks in the file, relative to the end of file.
void seekEnd( qint64 offset = 0 ) THROW_SPEC( exSeekError, exWriteError );
void seekEnd( qint64 offset = 0 ) ;
/// Seeks to the beginning of file
void rewind() THROW_SPEC( exSeekError, exWriteError );
void rewind() ;
/// Tells the current position within the file, relative to its beginning.
qint64 tell() THROW_SPEC( exSeekError );
qint64 tell() ;
/// Returns true if end-of-file condition is set.
bool eof() THROW_SPEC( exWriteError );
bool eof() ;
/// Returns the underlying FILE * record, so other operations can be
/// performed on it.
QFile & file() THROW_SPEC( exWriteError );
QFile & file() ;
/// Closes the file. No further operations are valid.
void close() THROW_SPEC( exWriteError );
void close() ;
~Class() throw();
private:
void flushWriteBuffer() THROW_SPEC( exWriteError );
void releaseWriteBuffer() THROW_SPEC( exWriteError );
void flushWriteBuffer() ;
void releaseWriteBuffer() ;
};
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -622,6 +622,8 @@ wstring trimWhitespaceOrPunct( wstring const & in )
wstring trimWhitespace( wstring const & in )
{
if( in.empty() )
return in;
wchar const * wordBegin = in.c_str();
wstring::size_type wordSize = in.size();

View file

@ -55,7 +55,7 @@ public:
{ return 0; }
virtual sptr< WordSearchRequest > prefixMatch( wstring const & /*word*/,
unsigned long /*maxResults*/ ) THROW_SPEC( std::exception )
unsigned long /*maxResults*/ )
{
sptr< WordSearchRequestInstant > sr = new WordSearchRequestInstant;
@ -66,7 +66,7 @@ public:
virtual sptr< DataRequest > getArticle( wstring const &, vector< wstring > const & alts,
wstring const &, bool )
THROW_SPEC( std::exception );
;
protected:
@ -77,7 +77,7 @@ protected:
sptr< DataRequest > ForvoDictionary::getArticle( wstring const & word,
vector< wstring > const & alts,
wstring const &, bool )
THROW_SPEC( std::exception )
{
if ( word.size() > 80 )
{
@ -347,7 +347,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
Dictionary::Initializing &,
Config::Forvo const & forvo,
QNetworkAccessManager & mgr )
THROW_SPEC( std::exception )
{
vector< sptr< Dictionary::Class > > result;

View file

@ -21,7 +21,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
Dictionary::Initializing &,
Config::Forvo const &,
QNetworkAccessManager & )
THROW_SPEC( std::exception );
;
/// Exposed here for moc
class ForvoArticleRequest: public Dictionary::DataRequest

View file

@ -71,10 +71,10 @@ bool parseSearchString( QString const & str, QStringList & indexWords,
{
searchWords.clear();
indexWords.clear();
QRegExp spacesRegExp( "\\W+" );
QRegExp wordRegExp( QString( "\\w{" ) + QString::number( FTS::MinimumWordSize ) + ",}" );
QRegExp setsRegExp( "\\[[^\\]]+\\]", Qt::CaseInsensitive, QRegExp::RegExp2 );
QRegExp regexRegExp( "\\\\[afnrtvdDwWsSbB]|\\\\x([0-9A-Fa-f]{4})|\\\\0([0-7]{3})", Qt::CaseSensitive, QRegExp::RegExp2 );
QRegularExpression spacesRegExp( "\\W+" );
QRegularExpression wordRegExp( QString( "\\w{" ) + QString::number( FTS::MinimumWordSize ) + ",}" );
QRegularExpression setsRegExp( "\\[[^\\]]+\\]", QRegularExpression::CaseInsensitiveOption );
QRegularExpression regexRegExp( "\\\\[afnrtvdDwWsSbB]|\\\\x([0-9A-Fa-f]{4})|\\\\0([0-7]{3})", QRegularExpression::CaseInsensitiveOption);
hasCJK = false;
for( int x = 0; x < str.size(); x++ )

View file

@ -2,7 +2,11 @@
#define __FTSHELPERS_HH_INCLUDED__
#include <QString>
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QRegExp>
#else
#include <QRegExp>
#endif
#include <QRunnable>
#include <QSemaphore>
#include <QList>

View file

@ -17,6 +17,7 @@
#include "initializing.hh"
#include <qt_windows.h>
#include <uxtheme.h>
#include <QOperatingSystemVersion>
#endif
@ -248,8 +249,7 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent,
oldBarStyle = 0;
if( QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA
&& ( QSysInfo::windowsVersion() & QSysInfo::WV_NT_based )
if( QOperatingSystemVersion::current () >= QOperatingSystemVersion::Windows7
&& !IsThemeActive() )
{
QStyle * barStyle = WindowsStyle::instance().getStyle();
@ -649,7 +649,7 @@ Q_UNUSED( parent );
for( int x = 0; x < hws.length(); x++ )
{
QList< FtsHeadword >::iterator it = qBinaryFind( headwords.begin(), headwords.end(), hws.at( x ) );
QList< FtsHeadword >::iterator it = std::lower_bound( headwords.begin(), headwords.end(), hws.at( x ) );
if( it != headwords.end() )
{
it->dictIDs.push_back( hws.at( x ).dictIDs.front() );

View file

@ -3,7 +3,11 @@
#include <QSemaphore>
#include <QStringList>
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QRegExp>
#else
#include <QRegExp>
#endif
#include <QAbstractListModel>
#include <QList>
#include <QAction>

View file

@ -1,9 +1,13 @@
/* This file is (c) 2013 Abs62
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include <QTextCodec>
#include <QString>
#include "gddebug.hh"
#if(QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QTextCodec>
#else
#include <QTextCodec>
#endif
QFile * logFilePtr;
static QTextCodec * utf8Codec;
@ -23,7 +27,7 @@ QTextCodec *localeCodec = 0;
QTextCodec::setCodecForLocale( utf8Codec );
}
qWarning( "%s", QString().vsprintf( msg, ap ).toUtf8().data() );
qWarning( "%s", QString().vasprintf( msg, ap ).toUtf8().data() );
if( logFilePtr && logFilePtr->isOpen() )
{
@ -48,7 +52,7 @@ QTextCodec *localeCodec = 0;
QTextCodec::setCodecForLocale( utf8Codec );
}
qDebug( "%s", QString().vsprintf( msg, ap ).toUtf8().data() );
qDebug( "%s", QString().vasprintf( msg, ap ).toUtf8().data() );
if( logFilePtr && logFilePtr->isOpen() )
{

View file

@ -1,13 +0,0 @@
.PHONY: all clean
all: ../inc_case_folding.hh ../inc_diacritic_folding.hh
generate: generate.cc
c++ -W -Wall $< -o $@
../inc_case_folding.hh ../inc_diacritic_folding.hh: CaseFolding.txt DiacriticFolding.txt generate
./generate
clean:
rm -f generate

View file

@ -40,7 +40,7 @@ GermanTable::GermanTable()
}
sptr< Dictionary::Class > makeDictionary() THROW_SPEC( std::exception )
sptr< Dictionary::Class > makeDictionary()
{
static GermanTable t;

View file

@ -9,7 +9,7 @@
// Support for German transliteration
namespace GermanTranslit {
sptr< Dictionary::Class > makeDictionary() THROW_SPEC( std::exception );
sptr< Dictionary::Class > makeDictionary() ;
}

60
gls.cc
View file

@ -32,7 +32,11 @@
#include <QBuffer>
#include <QRegularExpression>
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QTextCodec>
#else
#include <QTextCodec>
#endif
#include <string>
#include <list>
#include <map>
@ -83,7 +87,7 @@ public:
DEF_EX_STR( exMalformedGlsFile, "The .gls file is malformed:", Ex )
DEF_EX( exEncodingError, "Encoding error", Ex ) // Should never happen really
GlsScanner( string const & fileName ) THROW_SPEC( Ex, Iconv::Ex );
GlsScanner( string const & fileName ) ;
~GlsScanner() throw();
/// Returns the detected encoding of this file.
@ -116,13 +120,13 @@ public:
/// If end of file is reached, false is returned.
/// Reading begins from the first line after the headers (ones which end
/// by the "### Glossary section:" line).
bool readNextLine( wstring &, size_t & offset ) THROW_SPEC( Ex, Iconv::Ex );
bool readNextLine( wstring &, size_t & offset ) ;
/// Returns the number of lines read so far from the file.
unsigned getLinesRead() const
{ return linesRead; }
};
GlsScanner::GlsScanner( string const & fileName ) THROW_SPEC( Ex, Iconv::Ex ):
GlsScanner::GlsScanner( string const & fileName ) :
encoding( Utf8::Utf8 ), readBufferPtr( readBuffer ),
readBufferLeft( 0 ), linesRead( 0 )
{
@ -179,13 +183,13 @@ GlsScanner::GlsScanner( string const & fileName ) THROW_SPEC( Ex, Iconv::Ex ):
wstring str;
wstring *currentField = 0;
wstring mark = GD_NATIVE_TO_WS( L"###" );
wstring titleMark = GD_NATIVE_TO_WS( L"### Glossary title:" );
wstring authorMark = GD_NATIVE_TO_WS( L"### Author:" );
wstring descriptionMark = GD_NATIVE_TO_WS( L"### Description:" );
wstring langFromMark = GD_NATIVE_TO_WS( L"### Source language:" );
wstring langToMark = GD_NATIVE_TO_WS( L"### Target language:" );
wstring endOfHeaderMark = GD_NATIVE_TO_WS( L"### Glossary section:" );
wstring mark = U"###" ;
wstring titleMark = U"### Glossary title:" ;
wstring authorMark = U"### Author:" ;
wstring descriptionMark = U"### Description:" ;
wstring langFromMark = U"### Source language:" ;
wstring langToMark = U"### Target language:" ;
wstring endOfHeaderMark = U"### Glossary section:" ;
size_t offset;
for( ; ; )
@ -242,8 +246,7 @@ GlsScanner::GlsScanner( string const & fileName ) THROW_SPEC( Ex, Iconv::Ex ):
}
}
bool GlsScanner::readNextLine( wstring & out, size_t & offset ) THROW_SPEC( Ex,
Iconv::Ex )
bool GlsScanner::readNextLine( wstring & out, size_t & offset )
{
offset = (size_t)(gztell(f) - readBufferLeft);
@ -285,13 +288,8 @@ bool GlsScanner::readNextLine( wstring & out, size_t & offset ) THROW_SPEC( Ex,
readBufferPtr += pos;
linesRead++;
#ifdef __WIN32
out = line.toStdU32String();
#else
out = line.toStdWString();
#endif
return true;
}
}
@ -393,16 +391,16 @@ public:
{ return idxHeader.langTo; }
virtual sptr< Dictionary::WordSearchRequest > findHeadwordsForSynonym( wstring const & )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception );
;
virtual sptr< Dictionary::DataRequest > getResource( string const & name )
THROW_SPEC( std::exception );
;
virtual QString const& getDescription();
@ -766,7 +764,7 @@ QString & GlsDictionary::filterResource( QString & article )
while( it.hasNext() )
{
QRegularExpressionMatch match = it.next();
articleNewText += article.midRef( pos, match.capturedStart() - pos );
articleNewText += article.mid( pos, match.capturedStart() - pos );
pos = match.capturedEnd();
QString link = match.captured( 3 );
@ -798,7 +796,7 @@ QString & GlsDictionary::filterResource( QString & article )
}
if( pos )
{
articleNewText += article.midRef( pos );
articleNewText += article.mid( pos );
article = articleNewText;
articleNewText.clear();
}
@ -817,7 +815,7 @@ QString & GlsDictionary::filterResource( QString & article )
while( it.hasNext() )
{
QRegularExpressionMatch match = it.next();
articleNewText += article.midRef( pos, match.capturedStart() - pos );
articleNewText += article.mid( pos, match.capturedStart() - pos );
pos = match.capturedEnd();
QString src = match.captured( 2 );
@ -838,7 +836,7 @@ QString & GlsDictionary::filterResource( QString & article )
}
if( pos )
{
articleNewText += article.midRef( pos );
articleNewText += article.mid( pos );
article = articleNewText;
articleNewText.clear();
}
@ -979,7 +977,7 @@ void GlsHeadwordsRequest::run()
sptr< Dictionary::WordSearchRequest >
GlsDictionary::findHeadwordsForSynonym( wstring const & word )
THROW_SPEC( std::exception )
{
return synonymSearchEnabled ? new GlsHeadwordsRequest( word, *this ) :
Class::findHeadwordsForSynonym( word );
@ -1161,7 +1159,7 @@ sptr< Dictionary::DataRequest > GlsDictionary::getArticle( wstring const & word,
vector< wstring > const & alts,
wstring const &,
bool ignoreDiacritics )
THROW_SPEC( std::exception )
{
return new GlsArticleRequest( word, alts, *this, ignoreDiacritics );
}
@ -1337,7 +1335,7 @@ void GlsResourceRequest::run()
while( it.hasNext() )
{
QRegularExpressionMatch match = it.next();
newCSS += css.midRef( pos, match.capturedStart() - pos );
newCSS += css.mid( pos, match.capturedStart() - pos );
pos = match.capturedEnd();
QString url = match.captured( 2 );
@ -1355,7 +1353,7 @@ void GlsResourceRequest::run()
}
if( pos )
{
newCSS += css.midRef( pos );
newCSS += css.mid( pos );
css = newCSS;
newCSS.clear();
}
@ -1380,7 +1378,7 @@ void GlsResourceRequest::run()
}
sptr< Dictionary::DataRequest > GlsDictionary::getResource( string const & name )
THROW_SPEC( std::exception )
{
return new GlsResourceRequest( *this, name );
}
@ -1403,7 +1401,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
Dictionary::Initializing & initializing )
THROW_SPEC( std::exception )
{
vector< sptr< Dictionary::Class > > dictionaries;

2
gls.hh
View file

@ -13,7 +13,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
Dictionary::Initializing & )
THROW_SPEC( std::exception );
;
}

View file

@ -1,18 +1,18 @@
TEMPLATE = app
TARGET = goldendict
VERSION = 1.5.0-RC2+git
VERSION = 22.4.Summer
# Generate version file. We do this here and in a build rule described later.
# The build rule is required since qmake isn't run each time the project is
# rebuilt; and doing it here is required too since any other way the RCC
# compiler would complain if version.txt wouldn't exist (fresh checkouts).
system(git describe --tags --always --dirty > version.txt): hasGit=1
system(git describe --tags --always --dirty): hasGit=1
isEmpty( hasGit ) {
message(Failed to precisely describe the version via Git -- using the default version string)
system(echo $$VERSION > version.txt)
!isEmpty(hasGit){
GIT_HASH=$$system(git rev-parse --short=8 HEAD )
}
system(echo $${VERSION}.$${GIT_HASH} > version.txt)
# DEPENDPATH += . generators
INCLUDEPATH += .
@ -21,21 +21,23 @@ QT += core \
gui \
xml \
network \
svg
QT += widgets \
svg \
widgets \
webenginewidgets\
webchannel\
printsupport \
help
greaterThan(QT_MAJOR_VERSION, 5): QT += webenginecore core5compat
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
# QMediaPlayer is not available in Qt4.
!CONFIG( no_qtmultimedia_player ) {
QT += multimedia
DEFINES += MAKE_QTMULTIMEDIA_PLAYER
}
!CONFIG( no_ffmpeg_player ) {
DEFINES += MAKE_FFMPEG_PLAYER
}
@ -43,24 +45,32 @@ QT += widgets \
QT += sql
CONFIG += exceptions \
rtti \
stl
# lrelease #lrelease generate qm under target folder.
stl \
c++14 \
lrelease \
embed_translations
QM_FILES_INSTALL_PATH = /locale/
mac {
DEBUG:CONFIG += app_bundle
}
QM_FILES_RESOURCE_PREFIX = /locale/
OBJECTS_DIR = build
UI_DIR = build
MOC_DIR = build
RCC_DIR = build
#RCC_DIR = build
LIBS += \
-lz \
-lbz2 \
-llzo2
CONFIG+=utf8_source
win32 {
TARGET = GoldenDict
win32-msvc* {
VERSION = 1.5.0 # More complicated things cause errors during compilation under MSVC++
VERSION = 22.4.1 # VS does not recognize 22.2.xxx,cause errors during compilation under MSVC++
DEFINES += __WIN32 _CRT_SECURE_NO_WARNINGS
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += NOMINMAX __WIN64
@ -76,8 +86,7 @@ win32 {
HUNSPELL_LIB = hunspell
}
LIBS += -liconv \
-lwsock32 \
LIBS += -lwsock32 \
-lpsapi \
-lole32 \
-loleaut32 \
@ -94,8 +103,7 @@ win32 {
-lavcodec
}
RC_FILE = goldendict.rc
RC_ICONS += icons/programicon.ico icons/programicon_old.ico
INCLUDEPATH += winlibs/include
# Enable console in Debug mode on Windows, with useful logging messages
@ -105,8 +113,6 @@ win32 {
gcc48:QMAKE_CXXFLAGS += -Wno-unused-local-typedefs
CONFIG += zim_support
!CONFIG( no_chinese_conversion_support ) {
CONFIG += chinese_conversion_support
}
@ -116,13 +122,12 @@ win32 {
unix:!mac {
DEFINES += HAVE_X11
# This is to keep symbols for backtraces
QMAKE_CXXFLAGS += -rdynamic
QMAKE_LFLAGS += -rdynamic
QT += x11extras
lessThan(QT_MAJOR_VERSION, 6): QT += x11extras
greaterThan(QT_MAJOR_VERSION, 5): QT += gui-private
CONFIG += link_pkgconfig
PKGCONFIG += vorbisfile \
vorbis \
ogg \
@ -135,7 +140,7 @@ unix:!mac {
libswresample \
}
arm {
LIBS += -liconv
#LIBS += -liconv
} else {
LIBS += -lX11 -lXtst
}
@ -168,7 +173,7 @@ unix:!mac {
INSTALLS += helps
}
freebsd {
LIBS += -liconv -lexecinfo
LIBS += -lexecinfo
}
mac {
TARGET = GoldenDict
@ -178,52 +183,44 @@ mac {
# CONFIG += x86 x86_64 ppc
LIBS = -lz \
-lbz2 \
-liconv \
-lvorbisfile \
-lvorbis \
-logg \
-lhunspell-1.6.1 \
-lhunspell-1.7.0 \
-llzo2
!CONFIG( no_ffmpeg_player ) {
LIBS += -lao \
-lswresample-gd \
-lavutil-gd \
-lavformat-gd \
-lavcodec-gd
-lswresample \
-lavutil \
-lavformat \
-lavcodec
}
INCLUDEPATH = $${PWD}/maclibs/include
LIBS += -L$${PWD}/maclibs/lib -framework AppKit -framework Carbon
QT_CONFIG -= no-pkg-config
CONFIG += link_pkgconfig
INCLUDEPATH = /opt/homebrew/include /usr/local/include
LIBS += -L/opt/homebrew/lib -L/usr/local/lib -framework AppKit -framework Carbon
OBJECTIVE_SOURCES += lionsupport.mm \
machotkeywrapper.mm \
macmouseover.mm \
speechclient_mac.mm
ICON = icons/macicon.icns
QMAKE_INFO_PLIST = myInfo.plist
QMAKE_POST_LINK = mkdir -p GoldenDict.app/Contents/Frameworks & \
cp -nR $${PWD}/maclibs/lib/ GoldenDict.app/Contents/Frameworks/ & \
mkdir -p GoldenDict.app/Contents/MacOS/locale & \
cp -R locale/*.qm GoldenDict.app/Contents/MacOS/locale/ & \
mkdir -p GoldenDict.app/Contents/MacOS/help & \
QMAKE_POST_LINK = mkdir -p GoldenDict.app/Contents/Frameworks && \
mkdir -p GoldenDict.app/Contents/MacOS/help && \
cp -R $${PWD}/help/*.qch GoldenDict.app/Contents/MacOS/help/
CONFIG += zim_support
!CONFIG( no_chinese_conversion_support ) {
CONFIG += chinese_conversion_support
CONFIG( x86 ) {
QMAKE_POST_LINK += & mkdir -p GoldenDict.app/Contents/MacOS/opencc & \
cp -R $${PWD}/opencc/*.json GoldenDict.app/Contents/MacOS/opencc/ & \
cp -R $${PWD}/opencc/*.ocd GoldenDict.app/Contents/MacOS/opencc/
} else {
QMAKE_POST_LINK += & mkdir -p GoldenDict.app/Contents/MacOS/opencc & \
cp -R $${PWD}/opencc/x64/*.json GoldenDict.app/Contents/MacOS/opencc/ & \
cp -R $${PWD}/opencc/x64/*.ocd GoldenDict.app/Contents/MacOS/opencc/
}
QMAKE_POST_LINK += && mkdir -p GoldenDict.app/Contents/MacOS/opencc && \
cp -R $${PWD}/opencc/*.* GoldenDict.app/Contents/MacOS/opencc/
}
}
DEFINES += PROGRAM_VERSION=\\\"$$VERSION\\\"
# Input
HEADERS += folding.hh \
article_inspect.h \
globalbroadcaster.h \
inc_case_folding.hh \
inc_diacritic_folding.hh \
@ -268,7 +265,6 @@ HEADERS += folding.hh \
wordfinder.hh \
groupcombobox.hh \
keyboardstate.hh \
mouseover.hh \
preferences.hh \
mutex.hh \
mediawiki.hh \
@ -345,7 +341,6 @@ HEADERS += folding.hh \
gls.hh \
splitfile.hh \
favoritespanewidget.hh \
cpp_features.hh \
treeview.hh
FORMS += groups.ui \
@ -365,6 +360,7 @@ FORMS += groups.ui \
fulltextsearch.ui
SOURCES += folding.cc \
article_inspect.cpp \
globalbroadcaster.cpp \
main.cc \
dictionary.cc \
@ -404,7 +400,6 @@ SOURCES += folding.cc \
wordfinder.cc \
groupcombobox.cc \
keyboardstate.cc \
mouseover.cc \
preferences.cc \
mutex.cc \
mediawiki.cc \
@ -412,7 +407,6 @@ SOURCES += folding.cc \
hunspell.cc \
dictdfiles.cc \
audiolink.cc \
wstring.cc \
wstring_qt.cc \
processwrapper.cc \
hotkeywrapper.cc \
@ -484,19 +478,16 @@ win32 {
FORMS += texttospeechsource.ui
SOURCES += wordbyauto.cc \
guids.c \
x64.cc \
speechclient_win.cc \
texttospeechsource.cc \
speechhlp.cc
HEADERS += wordbyauto.hh \
uiauto.hh \
x64.hh \
texttospeechsource.hh \
sapi.hh \
sphelper.hh \
speechclient.hh \
speechhlp.hh \
hotkeys.h
speechhlp.hh
}
mac {
@ -549,20 +540,12 @@ CONFIG( chinese_conversion_support ) {
chineseconversion.hh
SOURCES += chinese.cc \
chineseconversion.cc
win32-msvc* {
Debug: LIBS += -lopenccd
Release: LIBS += -lopencc
} else {
mac {
LIBS += -lopencc.2
} else {
LIBS += -lopencc
}
}
}
RESOURCES += resources.qrc \
flags.qrc
#EXTRA_TRANSLATIONS += thirdparty/qwebengine_ts/qtwebengine_zh_CN.ts
TRANSLATIONS += locale/ru_RU.ts \
locale/zh_CN.ts \
locale/cs_CZ.ts \
@ -605,50 +588,10 @@ TRANSLATIONS += locale/ru_RU.ts \
# Build version file
!isEmpty( hasGit ) {
QMAKE_EXTRA_TARGETS += revtarget
PRE_TARGETDEPS += $$PWD/version.txt
revtarget.target = $$PWD/version.txt
!win32 {
revtarget.commands = cd $$PWD; git describe --tags --always --dirty > $$revtarget.target
} else {
revtarget.commands = git --git-dir=\"$$PWD/.git\" describe --tags --always --dirty > $$revtarget.target
}
ALL_SOURCES = $$SOURCES $$HEADERS $$FORMS
for(src, ALL_SOURCES) {
QUALIFIED_SOURCES += $${PWD}/$${src}
}
revtarget.depends = $$QUALIFIED_SOURCES
}
# This makes qmake generate translations
isEmpty(QMAKE_LRELEASE):QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
# The *.qm files might not exist when qmake is run for the first time,
# causing the standard install rule to be ignored, and no translations
# will be installed. With this, we create the qm files during qmake run.
!win32 {
system($${QMAKE_LRELEASE} -silent $${_PRO_FILE_} 2> /dev/null)
}
else{
system($${QMAKE_LRELEASE} -silent $${_PRO_FILE_})
}
updateqm.input = TRANSLATIONS
updateqm.output = locale/${QMAKE_FILE_BASE}.qm
updateqm.commands = $$QMAKE_LRELEASE \
${QMAKE_FILE_IN} \
-qm \
${QMAKE_FILE_OUT}
updateqm.CONFIG += no_link
QMAKE_EXTRA_COMPILERS += updateqm
TS_OUT = $$TRANSLATIONS
TS_OUT ~= s/.ts/.qm/g
PRE_TARGETDEPS += $$TS_OUT
include( qtsingleapplication/src/qtsingleapplication.pri )
include( thirdparty/qtsingleapplication/src/qtsingleapplication.pri )

View file

@ -1,39 +0,0 @@
#include "windows.h"
IDI_ICON1 ICON DISCARDABLE "icons/programicon.ico"
IDI_ICON2 ICON DISCARDABLE "icons/programicon_old.ico"
#define GOLDENDICT_VER 1,5,0,0
#define GOLDENDICT_VER_STR "1.5.0"
#if !defined( _MSC_VER ) && !defined( GD_NO_MANIFEST ) // Visual Studio embeds the manifest automatically
1 RT_MANIFEST GoldenDict.exe.manifest
#endif
1 VERSIONINFO
FILEVERSION GOLDENDICT_VER
PRODUCTVERSION GOLDENDICT_VER
FILEFLAGS 0x0L
FILEFLAGSMASK 0x3fL
FILEOS 0x00040004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "CompanyName", "GoldenDict"
VALUE "FileDescription", "GoldenDict dictionary lookup program"
VALUE "FileVersion", GOLDENDICT_VER_STR
VALUE "LegalCopyright", "www.goldendict.org"
VALUE "InternalName", "goldendict"
VALUE "OriginalFilename", "goldendict.exe"
VALUE "ProductName", "GoldenDict"
VALUE "ProductVersion", GOLDENDICT_VER_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END

View file

@ -831,7 +831,7 @@ GreekTable::GreekTable()
}
sptr< Dictionary::Class > makeDictionary() THROW_SPEC( std::exception )
sptr< Dictionary::Class > makeDictionary()
{
static GreekTable t;

View file

@ -9,7 +9,7 @@
// Support for Greek transliteration
namespace GreekTranslit {
sptr< Dictionary::Class > makeDictionary() THROW_SPEC( std::exception );
sptr< Dictionary::Class > makeDictionary() ;
}

View file

@ -20,7 +20,7 @@ Groups::Groups( QWidget * parent,
// Populate the dictionaries' list
ui.dictionaries->setAsSource();
ui.dictionaries->populate( Instances::Group( order, dicts, Config::Group() ).dictionaries,
ui.dictionaries->populate( Instances::Group( order, Dictionary::dictToMap(dicts), Config::Group() ).dictionaries,
dicts );
ui.searchLine->applyTo( ui.dictionaries );
@ -87,14 +87,13 @@ void Groups::editGroup( unsigned id )
void Groups::updateDictionaryOrder( Config::Group const & order )
{
// Make sure it differs from what we have
Instances::Group newOrder( order, dicts, Config::Group() );
auto dictMap = Dictionary::dictToMap( dicts );
Instances::Group newOrder( order, dictMap, Config::Group() );
if( ui.dictionaries->getCurrentDictionaries() != newOrder.dictionaries )
{
// Repopulate
ui.dictionaries->populate( Instances::Group( order, dicts, Config::Group() ).dictionaries,
dicts );
ui.dictionaries->populate( Instances::Group( order, dictMap, Config::Group() ).dictionaries, dicts );
}
}

View file

@ -31,7 +31,8 @@ DictGroupWidget::DictGroupWidget( QWidget * parent,
groupId( group.id )
{
ui.setupUi( this );
ui.dictionaries->populate( Instances::Group( group, dicts, Config::Group() ).dictionaries, dicts );
auto dictMap = Dictionary::dictToMap(dicts);
ui.dictionaries->populate( Instances::Group( group, dictMap, Config::Group() ).dictionaries, dicts );
// Populate icons' list
@ -260,7 +261,7 @@ QVariant DictListModel::data( QModelIndex const & index, int role ) const
case Qt::DecorationRole:
// make all icons of the same size to avoid visual size/alignment problems
return item->getIcon().pixmap( 32 ).scaledToHeight( 21, Qt::SmoothTransformation );
return item->getIcon();
default:;
}
@ -328,7 +329,7 @@ bool DictListModel::setData( QModelIndex const & index, const QVariant & value,
g.dictionaries.push_back( Config::DictionaryRef( value.toString(), QString() ) );
Instances::Group i( g, *allDicts, Config::Group() );
Instances::Group i( g, Dictionary::dictToMap(*allDicts), Config::Group() );
if ( i.dictionaries.size() == 1 )
{
@ -584,8 +585,7 @@ void DictGroupsWidget::populate( Config::Groups const & groups,
{
DictGroupWidget *gr = new DictGroupWidget( this, *allDicts, groups[ x ] );
addTab( gr, escapeAmps( groups[ x ].name ) );
connect( gr, SIGNAL( showDictionaryInfo( QString const & ) ),
this, SIGNAL( showDictionaryInfo( QString const & ) ) );
connect( gr, &DictGroupWidget::showDictionaryInfo,this, &DictGroupsWidget::showDictionaryInfo );
connect( gr->getModel(), SIGNAL( contentChanged() ), this, SLOT( tabDataChanged() ) );
setCurrentIndex( x );
@ -744,8 +744,8 @@ void DictGroupsWidget::addAutoGroups()
dictMap[ name ] = vd;
}
QStringList groupList = dictMap.uniqueKeys();
QStringList morphoList = morphoMap.uniqueKeys();
QStringList groupList = dictMap.keys();
QStringList morphoList = morphoMap.keys();
// Insert morphology dictionaries into corresponding lists

View file

@ -11,6 +11,7 @@
#include "helpwindow.hh"
#include "gddebug.hh"
#include <QHelpLink>
namespace Help {
@ -25,9 +26,11 @@ void HelpBrowser::showHelpForKeyword( QString const & id )
{
if ( helpEngine )
{
QMap< QString, QUrl > links = helpEngine->linksForIdentifier( id );
if( !links.isEmpty() )
setSource( links.constBegin().value() );
QList<QHelpLink> links = helpEngine->documentsForIdentifier(id);
if (!links.isEmpty()) {
QHelpLink link=links.constFirst();
setSource(link.url);
}
}
}
@ -251,7 +254,7 @@ void HelpWindow::applyZoomFactor()
zoomInAction->setEnabled( cfg.preferences.helpZoomFactor < 5 );
zoomOutAction->setEnabled( cfg.preferences.helpZoomFactor > 0.2 );
zoomBaseAction->setEnabled( cfg.preferences.helpZoomFactor != 1.0 );
zoomBaseAction->setEnabled( !qFuzzyCompare(cfg.preferences.helpZoomFactor, 1.0) );
if( fontSize > 0 )
{

View file

@ -87,7 +87,7 @@ void HotKeyEdit::keyPressEvent( QKeyEvent * event )
// Delete current combo
currentKey1 = 0;
currentKey2 = 0;
currentModifiers = 0;
currentModifiers = Qt::NoModifier;
continuingCombo = false;
}
else

211
hotkeys.c
View file

@ -1,211 +0,0 @@
#include <windows.h>
#include "hotkeys.h"
#include "stdio.h"
static LRESULT CALLBACK lowLevelKeyboardProc(int, WPARAM, LPARAM);
// Max number of hotkeys
#define MAX_HOTKEYS 5
// Max time interval between first and second part of hotkey (ms)
#define MAX_KEYS_TIME_INTERVAL 500
static HINSTANCE hInstance;
static HWND hGDWindow;
static HHOOK hKbdHook;
typedef struct HotkeyStruct
{
DWORD key1;
DWORD key2;
DWORD mods;
DWORD lasttime;
} HotkeyStruct;
static HotkeyStruct hotkeys[ MAX_HOTKEYS ];
__declspec (dllexport) void removeHook()
{
if( hKbdHook )
{
UnhookWindowsHookEx( hKbdHook );
hKbdHook = 0;
}
}
__declspec (dllexport) BOOL setHook( HWND hwnd )
{
hGDWindow = hwnd;
removeHook();
hKbdHook = SetWindowsHookEx( WH_KEYBOARD_LL, lowLevelKeyboardProc, hInstance, 0 );
return hKbdHook != 0;
}
__declspec (dllexport) BOOL setHotkeys( DWORD key1, DWORD key2, DWORD modifiers, int nom )
{
if( nom < 0 || nom >= MAX_HOTKEYS )
return FALSE;
hotkeys[ nom ].key1 = key1;
hotkeys[ nom ].key2 = key2;
hotkeys[ nom ].mods = modifiers;
hotkeys[ nom ].lasttime = 0;
return TRUE;
}
__declspec (dllexport) void clearHotkeys()
{
int i;
for( i = 0; i < MAX_HOTKEYS; i++ )
memset( hotkeys + i, 0, sizeof( HotkeyStruct ) );
}
static BOOL isModifiersPressed( DWORD modifiers )
{
int n = GetAsyncKeyState( VK_MENU ) & 0x8000;
if( ( ( modifiers & MOD_ALT ) && n == 0 )
|| ( ( modifiers & MOD_ALT ) == 0 && n ) )
return FALSE;
n = GetAsyncKeyState( VK_SHIFT ) & 0x8000;
if( ( ( modifiers & MOD_SHIFT ) && n == 0 )
|| ( ( modifiers & MOD_SHIFT ) == 0 && n ) )
return FALSE;
n = GetAsyncKeyState( VK_CONTROL ) & 0x8000;
if( ( ( modifiers & MOD_CONTROL ) && n == 0 )
|| ( ( modifiers & MOD_CONTROL ) == 0 && n ) )
return FALSE;
n = ( GetAsyncKeyState( VK_LWIN ) & 0x8000 ) | ( GetAsyncKeyState( VK_RWIN ) & 0x8000 );
if( ( ( modifiers & MOD_WIN ) && n == 0 )
|| ( ( modifiers & MOD_WIN ) == 0 && n ) )
return FALSE;
return TRUE;
}
static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int i;
PKBDLLHOOKSTRUCT p;
BOOL stop = FALSE;
if ( nCode < 0 ) return CallNextHookEx( hKbdHook, nCode, wParam, lParam );
if( nCode == HC_ACTION )
{
p = (PKBDLLHOOKSTRUCT)lParam;
for( ; ; )
{
// Check hotkeys
if( wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN )
{
DWORD new_time = GetTickCount();
// Check if key is second part of hotkey
for( i = 0; i < MAX_HOTKEYS; i++ )
{
if( hotkeys[ i ].key1 == 0 )
break;
if( hotkeys[ i ].key2 == 0 || hotkeys[ i ].lasttime == 0 )
continue;
if( hotkeys[ i ].key2 == p->vkCode && isModifiersPressed( hotkeys[ i ].mods ) )
{
if( new_time - hotkeys[ i ].lasttime <= MAX_KEYS_TIME_INTERVAL )
{
// Hotkey completed
// Clear all flags for first part
int j;
for( j = 0; j < MAX_HOTKEYS; j++ )
hotkeys[ j ].lasttime = 0;
PostMessage( hGDWindow, GD_HOTKEY_MESSAGE, (WPARAM)i, 0 );
stop = TRUE;
break;
}
else
{
// Interval exceeded, reset time
hotkeys[ i ].lasttime = new_time;
continue;
}
}
else
{
// Key is not second part, clear flag
hotkeys[ i ].lasttime = 0;
}
}
if( stop )
break;
// Check if key is first part of hotkey
for( i = 0; i < MAX_HOTKEYS; i++ )
{
if( hotkeys[ i ].key1 == 0 )
break;
if( hotkeys[ i ].key1 == p->vkCode && isModifiersPressed( hotkeys[ i ].mods ) )
{
// Match found
if( hotkeys[ i ].key2 == 0 )
{
// No second part, hotkey completed
// Clear all flags for first part
int j;
for( j = 0; j < MAX_HOTKEYS; j++ )
hotkeys[ j ].lasttime = 0;
PostMessage( hGDWindow, GD_HOTKEY_MESSAGE, (WPARAM)i, 0 );
stop = TRUE;
break;
}
else
{
// First part detected, need wait for second part
hotkeys[ i ].lasttime = new_time;
break;
}
}
}
}
break;
}
}
LRESULT result = CallNextHookEx(hKbdHook, nCode, wParam, lParam);
return ( stop ? 1 : result );
}
BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
(void) reserved;
switch (reason)
{
case DLL_PROCESS_ATTACH:
hInstance = hInst;
break;
case DLL_PROCESS_DETACH:
removeHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}

View file

@ -1,14 +0,0 @@
#ifndef __HOTKEYS_H_INCLUDED__
#define __HOTKEYS_H_INCLUDED__
#include <windows.h>
// Message if hotkey completed; WPARAM - hotkey number
#define GD_HOTKEY_MESSAGE ( WM_APP + 1 )
typedef BOOL ( *setHookProc )( HWND hwnd );
typedef void ( *removeHookProc )();
typedef BOOL ( *setHotkeysProc )( DWORD, DWORD, DWORD, int );
typedef void ( *clearHotkeysProc )();
#endif // __HOTKEYS_H_INCLUDED__

View file

@ -1,22 +0,0 @@
#-------------------------------------------------
#
# DLL for global hotkeys handling
# Should be build for Windows only
# Place GdHotkey.dll beside GoldenDict.exe
#
#-------------------------------------------------
win32 {
QT -= core gui
TARGET = GdHotkeys
TEMPLATE = lib
DEFINES += HOTKEYS_LIBRARY
SOURCES += \
hotkeys.c
HEADERS += \
hotkeys.h \
}

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