mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-23 16:04:06 +00:00
release version 22.4
use 22.4.Summer as release version
This commit is contained in:
commit
15926efd95
|
@ -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
|
||||
|
||||
...
|
||||
|
|
9
.github/scripts/windows-publish.ps1
vendored
9
.github/scripts/windows-publish.ps1
vendored
|
@ -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
51
.github/workflows/AutoTag.yml
vendored
Normal 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 }}
|
||||
|
||||
|
||||
|
84
.github/workflows/codeql-analysis.yml
vendored
84
.github/workflows/codeql-analysis.yml
vendored
|
@ -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
123
.github/workflows/macos-6.2.yml
vendored
Normal 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
127
.github/workflows/macos-m1.yml
vendored
Normal 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
124
.github/workflows/macos.yml
vendored
Normal 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
134
.github/workflows/ubuntu-6.2.yml
vendored
Normal 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 }}
|
102
.github/workflows/ubuntu.yml
vendored
102
.github/workflows/ubuntu.yml
vendored
|
@ -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
170
.github/workflows/windows-6.2.yml
vendored
Normal 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:-)
|
119
.github/workflows/windows.yml
vendored
119
.github/workflows/windows.yml
vendored
|
@ -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
|
||||
|
@ -25,13 +40,19 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
# 5.15.2 参考 https://mirrors.cloud.tencent.com/qt/online/qtsdkrepository/windows_x86/desktop/qt5_5152/
|
||||
- qt_ver: 5.15.2
|
||||
- qt_ver: 5.15.2
|
||||
qt_arch: win64_msvc2019_64
|
||||
msvc_arch: x64
|
||||
qt_target: x64
|
||||
qt_arch_install: msvc2019_64
|
||||
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
10
.gitignore
vendored
|
@ -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
|
||||
|
|
56
CHANGES.md
56
CHANGES.md
|
@ -1,21 +1,43 @@
|
|||
# all the changes:
|
||||
- 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"
|
||||
- remove iconv partly,use qtextcodec instead.
|
||||
- when parse mdx dictionary ,use qtextcodec
|
||||
- when parse dsl dictionary ,use qtextcodec instead of iconv
|
||||
# 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"
|
||||
- remove iconv partly,use qtextcodec instead.
|
||||
- when parse mdx dictionary ,use qtextcodec
|
||||
- when parse dsl dictionary ,use qtextcodec instead of iconv
|
||||
|
||||
fix the old bug https://github.com/goldendict/goldendict/issues/1322 by the way
|
||||
- remove dependency of iconv lib completely,use qtextcodec instead. has not merge into this PR yet. in this branch https://github.com/xiaoyifang/goldendict/tree/remove-iconv-lib
|
||||
- bug, found dictionaries panel show all the dictionaries which is not correct.
|
||||
- bug,F12 inspect function.
|
||||
- bug ,double click event.in webengineview widget. the mouse event was eated by child widget.
|
||||
fix the old bug https://github.com/goldendict/goldendict/issues/1322 by the way
|
||||
- remove dependency of iconv lib completely,use qtextcodec instead. has not merge into this PR yet. in this branch https://github.com/xiaoyifang/goldendict/tree/remove-iconv-lib
|
||||
- bug, found dictionaries panel show all the dictionaries which is not correct.
|
||||
- bug,F12 inspect function.
|
||||
- bug ,double click event.in webengineview widget. the mouse event was eated by child widget.
|
||||
- bug,bword link (hunspell dictionary) navigation error.
|
||||
- single click to select the word ~(**work inside iframe**)~
|
||||
- Fix:open image url in external viewer. (only worked with external images)
|
||||
|
|
|
@ -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>
|
30
README.md
30
README.md
|
@ -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)
|
||||
|
|
9
aard.cc
9
aard.cc
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
2
aard.hh
2
aard.hh
|
@ -17,7 +17,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
string const & indicesDir,
|
||||
Dictionary::Initializing &,
|
||||
unsigned maxHeadwordsToExpand )
|
||||
THROW_SPEC( std::exception );
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
37
article_inspect.cpp
Normal 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
24
article_inspect.h
Normal 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
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
642
articleview.cc
642
articleview.cc
|
@ -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,14 +205,11 @@ 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_,
|
||||
GroupComboBox const * groupComboBox_ ):
|
||||
Instances::Groups const & groups_, bool popupView_, Config::Class const & cfg_,
|
||||
QAction & openSearchAction_, QAction * dictionaryBarToggled_,
|
||||
GroupComboBox const * groupComboBox_ ) :
|
||||
QFrame( parent ),
|
||||
articleNetMgr( nm ),
|
||||
audioPlayer( audioPlayer_ ),
|
||||
|
@ -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);
|
||||
onJsActiveArticleChanged(id);
|
||||
ui.definition->page()->runJavaScript(script);
|
||||
ui.definition->setProperty("currentArticle",id);
|
||||
setActiveArticleId(id.mid(7));
|
||||
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 );
|
||||
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;
|
||||
if( ca.isEmpty() )
|
||||
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,39 +698,41 @@ 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();
|
||||
isFramedArticle( ca,
|
||||
[ &url, &contexts, &ca ]( bool framed )
|
||||
{
|
||||
if( framed )
|
||||
{
|
||||
// QVariant result = runJavaScriptSync( ui.definition->page(), "gdLastUrlText" );
|
||||
QVariant result;
|
||||
|
||||
if ( isFramedArticle( ca ) )
|
||||
{
|
||||
//QVariant result = runJavaScriptSync( ui.definition->page(), "gdLastUrlText" );
|
||||
QVariant result ;
|
||||
if( result.type() == QVariant::String )
|
||||
{
|
||||
// Looks this way
|
||||
contexts[ dictionaryIdFromScrollTo( ca ) ] = QString::fromLatin1( url.toEncoded() );
|
||||
|
||||
if ( result.type() == QVariant::String )
|
||||
{
|
||||
// Looks this way
|
||||
contexts[ dictionaryIdFromScrollTo( ca ) ] = QString::fromLatin1( url.toEncoded() );
|
||||
QUrl target;
|
||||
|
||||
QUrl target;
|
||||
QString queryWord = result.toString();
|
||||
|
||||
QString queryWord = result.toString();
|
||||
// Empty requests are treated as no request, so we work this around by
|
||||
// adding a space.
|
||||
if( queryWord.isEmpty() )
|
||||
queryWord = " ";
|
||||
|
||||
// Empty requests are treated as no request, so we work this around by
|
||||
// adding a space.
|
||||
if ( queryWord.isEmpty() )
|
||||
queryWord = " ";
|
||||
target.setScheme( "gdlookup" );
|
||||
target.setHost( "localhost" );
|
||||
target.setPath( "/" + queryWord );
|
||||
|
||||
target.setScheme( "gdlookup" );
|
||||
target.setHost( "localhost" );
|
||||
target.setPath( "/" + queryWord );
|
||||
|
||||
url = target;
|
||||
}
|
||||
}
|
||||
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" );
|
||||
if ( v.type() == QVariant::String )
|
||||
return !v.toString().isEmpty();
|
||||
return false;
|
||||
ui.definition->page()->runJavaScript( "gdAudioLinks.first",
|
||||
[ callback ]( const QVariant & v )
|
||||
{
|
||||
bool has = false;
|
||||
if( v.type() == QVariant::String )
|
||||
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);
|
||||
if (!soundScript.isEmpty())
|
||||
openLink(QUrl::fromEncoded(soundScript.toUtf8()), ui.definition->url());
|
||||
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();
|
||||
}
|
||||
});
|
||||
loop->exec();
|
||||
return result;
|
||||
ui.definition->page()->toHtml(
|
||||
[ = ]( const QString & content )
|
||||
{
|
||||
QString html = content;
|
||||
callback( html );
|
||||
} );
|
||||
}
|
||||
|
||||
void ArticleView::setHtml(const QString& content,const QUrl& baseUrl){
|
||||
|
@ -1688,15 +1701,24 @@ 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(); };
|
||||
ui.definition->page()->print(printer, std::move(printPreview));
|
||||
loop.exec();
|
||||
if (!result) {
|
||||
qDebug()<<"print failed";
|
||||
}
|
||||
QEventLoop loop;
|
||||
bool result;
|
||||
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 )
|
||||
{
|
||||
qDebug() << "print failed";
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleView::contextMenuRequested( QPoint const & pos )
|
||||
|
@ -1720,10 +1742,14 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
QAction * addHeaderToHistoryAction = 0;
|
||||
QAction * sendWordToInputLineAction = 0;
|
||||
QAction * saveImageAction = 0;
|
||||
QAction * saveSoundAction = 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,19 +2172,21 @@ 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() )
|
||||
{
|
||||
QStringList lst = getArticlesList();
|
||||
currentDictId = lst[ 0 ];
|
||||
}
|
||||
|
||||
int idx = lst.indexOf( dictionaryIdFromScrollTo( current ) );
|
||||
int idx = lst.indexOf( currentDictId );
|
||||
|
||||
if ( idx != -1 )
|
||||
{
|
||||
idx = ( idx + 1 ) % lst.size();
|
||||
if( idx != -1 )
|
||||
{
|
||||
idx = ( idx + 1 ) % lst.size();
|
||||
|
||||
setCurrentArticle( scrollToFromDictionaryId( lst[ idx ] ), true );
|
||||
}
|
||||
setCurrentArticle( scrollToFromDictionaryId( lst[ idx ] ), true );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
} });
|
||||
{
|
||||
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,84 +2513,69 @@ 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() )
|
||||
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());
|
||||
marksHandler->setText( pageText );
|
||||
|
||||
QRegularExpressionMatchIterator it = regexp.globalMatch( marksHandler->normalizedText() );
|
||||
while( it.hasNext() )
|
||||
{
|
||||
QRegularExpressionMatch match = it.next();
|
||||
|
||||
// Mirror pos and matched length to original string
|
||||
int pos = match.capturedStart();
|
||||
int spos = marksHandler->mirrorPosition( pos );
|
||||
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 )
|
||||
matched++;
|
||||
|
||||
if( matched > FTS::MaxMatchLengthForHighlightResults )
|
||||
ui.definition->page()->toPlainText(
|
||||
[ & ]( const QString pageText )
|
||||
{
|
||||
gdWarning( "ArticleView::highlightFTSResults(): Too long match - skipped (matched length %i, allowed %i)",
|
||||
match.capturedLength(), FTS::MaxMatchLengthForHighlightResults );
|
||||
}
|
||||
else
|
||||
allMatches.append( pageText.mid( spos, matched ) );
|
||||
}
|
||||
marksHandler->setText( pageText );
|
||||
|
||||
ftsSearchMatchCase = Utils::Url::hasQueryItem( url, "matchcase" );
|
||||
QRegularExpressionMatchIterator it = regexp.globalMatch( marksHandler->normalizedText() );
|
||||
while( it.hasNext() )
|
||||
{
|
||||
QRegularExpressionMatch match = it.next();
|
||||
|
||||
QWebEnginePage::FindFlags flags ( 0 );
|
||||
// Mirror pos and matched length to original string
|
||||
int pos = match.capturedStart();
|
||||
int spos = marksHandler->mirrorPosition( pos );
|
||||
int matched = marksHandler->mirrorPosition( pos + match.capturedLength() ) - spos;
|
||||
|
||||
if( ftsSearchMatchCase )
|
||||
flags |= QWebEnginePage::FindCaseSensitively;
|
||||
// Add mark pos (if presented)
|
||||
while( spos + matched < pageText.length() && pageText[ spos + matched ].category() == QChar::Mark_NonSpacing )
|
||||
matched++;
|
||||
|
||||
for( int x = 0; x < allMatches.size(); x++ )
|
||||
ui.definition->findText( allMatches.at( x ), flags );
|
||||
if( matched > FTS::MaxMatchLengthForHighlightResults )
|
||||
{
|
||||
gdWarning( "ArticleView::highlightFTSResults(): Too long match - skipped (matched length %i, allowed %i)",
|
||||
match.capturedLength(),
|
||||
FTS::MaxMatchLengthForHighlightResults );
|
||||
}
|
||||
else
|
||||
allMatches.append( pageText.mid( spos, matched ) );
|
||||
}
|
||||
|
||||
if( !allMatches.isEmpty() )
|
||||
{
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
ftsSearchMatchCase = Utils::Url::hasQueryItem( url, "matchcase" );
|
||||
|
||||
ui.ftsSearchFrame->show();
|
||||
ui.ftsSearchPrevious->setEnabled( false );
|
||||
ui.ftsSearchNext->setEnabled( allMatches.size()>1 );
|
||||
QWebEnginePage::FindFlags flags( 0 );
|
||||
|
||||
ftsSearchIsOpened = true;
|
||||
}
|
||||
if( ftsSearchMatchCase )
|
||||
flags |= QWebEnginePage::FindCaseSensitively;
|
||||
|
||||
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;
|
||||
for( int x = 0; x < allMatches.size(); x++ )
|
||||
ui.definition->findText( allMatches.at( x ), flags );
|
||||
|
||||
if( !allMatches.isEmpty() )
|
||||
{
|
||||
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.ftsSearchFrame->show();
|
||||
ui.ftsSearchPrevious->setEnabled( false );
|
||||
ui.ftsSearchNext->setEnabled( allMatches.size() > 1 );
|
||||
|
||||
ftsSearchIsOpened = true;
|
||||
} );
|
||||
}
|
||||
|
||||
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 ),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,19 +35,30 @@ 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) {
|
||||
QChildEvent *child_ev = static_cast<QChildEvent *>(event);
|
||||
if( event->type() == QEvent::ChildAdded )
|
||||
{
|
||||
QChildEvent * child_ev = static_cast< QChildEvent * >( event );
|
||||
child_ev->child()->installEventFilter( this );
|
||||
}
|
||||
|
||||
// // 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);
|
||||
}
|
||||
|
||||
return QWebEngineView::event(event);
|
||||
return QWebEngineView::event( event );
|
||||
}
|
||||
|
||||
void ArticleWebView::linkClickedInHtml(QUrl const& ){
|
||||
|
@ -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) {
|
||||
QFocusEvent *pe = static_cast<QFocusEvent *>(ev);
|
||||
focusInEvent(pe);
|
||||
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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
23
autotests/goldendict-test.pro
Normal file
23
autotests/goldendict-test.pro
Normal 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
|
49
autotests/test-qtextcodec-convert.cpp
Normal file
49
autotests/test-qtextcodec-convert.cpp
Normal 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"
|
|
@ -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;
|
||||
|
|
|
@ -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
37
bgl.cc
|
@ -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
2
bgl.hh
|
@ -23,7 +23,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
vector< string > const & fileNames,
|
||||
string const & indicesDir,
|
||||
Dictionary::Initializing & )
|
||||
THROW_SPEC( std::exception );
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
102
btreeidx.cc
102
btreeidx.cc
|
@ -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
|
||||
|
@ -615,20 +615,10 @@ char const * BtreeIndex::findChainOffsetExactOrPrefix( wstring const & target,
|
|||
--closestString;
|
||||
|
||||
size_t wordSize = strlen( closestString );
|
||||
|
||||
if ( wcharBuffer.size() <= wordSize )
|
||||
wcharBuffer.resize( wordSize + 1 );
|
||||
|
||||
long result = Utf8::decode( closestString, wordSize, &wcharBuffer.front() );
|
||||
|
||||
if ( result < 0 )
|
||||
throw Utf8::exCantDecode( closestString );
|
||||
|
||||
wcharBuffer[ result ] = 0;
|
||||
w_word = Utf8::decode( string( closestString, wordSize ) );
|
||||
|
||||
//GD_DPRINTF( "Checking against %s\n", closestString );
|
||||
|
||||
compareResult = target.compare( &wcharBuffer.front() );
|
||||
compareResult = target.compare( w_word);
|
||||
|
||||
if ( !compareResult )
|
||||
{
|
||||
|
@ -749,22 +739,12 @@ char const * BtreeIndex::findChainOffsetExactOrPrefix( wstring const & target,
|
|||
ptr += sizeof( uint32_t );
|
||||
|
||||
size_t wordSize = strlen( ptr );
|
||||
|
||||
w_word = Utf8::decode( string( ptr, wordSize ) );
|
||||
|
||||
if ( wcharBuffer.size() <= wordSize )
|
||||
wcharBuffer.resize( wordSize + 1 );
|
||||
|
||||
//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 );
|
||||
|
||||
|
@ -1071,22 +1051,10 @@ void IndexedWords::addWord( wstring const & word, uint32_t articleOffset, unsign
|
|||
|
||||
// Safeguard us against various bugs here. Don't attempt adding words
|
||||
// which are freakishly huge.
|
||||
if ( wordSize > maxHeadwordSize )
|
||||
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 ) );
|
||||
}
|
||||
|
@ -1142,24 +1104,15 @@ 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;
|
||||
|
||||
if ( ( i->second.size() < 1024 ) || ( nextChar == wordBegin ) ) // Don't overpopulate chains with middle matches
|
||||
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( &utfBuffer.front(),
|
||||
Utf8::encode( nextChar, wordSize - ( nextChar - wordBegin ), &utfBuffer.front() ) );
|
||||
|
||||
string utfPrefix( &utfBuffer.front(),
|
||||
Utf8::encode( wordBegin, nextChar - wordBegin, &utfBuffer.front() ) );
|
||||
|
||||
string utfWord = Utf8::encode( wstring( nextChar, wordSize - ( nextChar - wordBegin ) ) );
|
||||
|
||||
string utfPrefix = Utf8::encode( wstring( wordBegin, nextChar - wordBegin ) );
|
||||
|
||||
i->second.push_back( WordArticleLink( utfWord, articleOffset, utfPrefix ) );
|
||||
}
|
||||
|
||||
|
@ -1437,16 +1390,17 @@ 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() )
|
||||
if( it!=offsets.end())
|
||||
{
|
||||
if( isCancelled && Utils::AtomicInt::loadAcquire( *isCancelled ) )
|
||||
return;
|
||||
|
||||
headwords.append( QString::fromUtf8( ( result[ i ].prefix + result[ i ].word ).c_str() ) );
|
||||
offsets.erase( it );
|
||||
offsets.erase( it);
|
||||
begOffsets = offsets.begin();
|
||||
endOffsets = offsets.end();
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
42
chinese.cc
42
chinese.cc
|
@ -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;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
namespace Chinese {
|
||||
|
||||
std::vector< sptr< Dictionary::Class > > makeDictionaries( Config::Chinese const & )
|
||||
THROW_SPEC( std::exception );
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
47
config.cc
47
config.cc
|
@ -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,12 +2285,17 @@ QString getProgramDataDir() throw()
|
|||
#endif
|
||||
}
|
||||
|
||||
QString getEmbedLocDir() throw()
|
||||
{
|
||||
return ":/locale";
|
||||
}
|
||||
|
||||
QString getLocDir() throw()
|
||||
{
|
||||
if ( QDir( getProgramDataDir() ).cd( "locale" ) )
|
||||
return getProgramDataDir() + "/locale";
|
||||
else
|
||||
return QCoreApplication::applicationDirPath() + "/locale";
|
||||
if ( QDir( getProgramDataDir() ).cd( "locale" ) )
|
||||
return getProgramDataDir() + "/locale";
|
||||
else
|
||||
return QCoreApplication::applicationDirPath() + "/locale";
|
||||
}
|
||||
|
||||
QString getHelpDir() throw()
|
||||
|
@ -2348,7 +2357,7 @@ QString getPortableVersionMorphoDir() throw()
|
|||
return QString();
|
||||
}
|
||||
|
||||
QString getStylesDir() throw()
|
||||
QString getStylesDir()
|
||||
{
|
||||
QDir result = getHomeDir();
|
||||
|
||||
|
|
25
config.hh
25
config.hh
|
@ -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();
|
||||
|
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
#include <QStyleOptionViewItemV4>
|
||||
#include <QStyleOptionViewItem>
|
||||
|
||||
#include "delegate.hh"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
vector< string > const & fileNames,
|
||||
string const & indicesDir,
|
||||
Dictionary::Initializing & )
|
||||
THROW_SPEC( std::exception );
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ using std::string;
|
|||
|
||||
vector< sptr< Dictionary::Class > > makeDictionaries(
|
||||
Config::DictServers const & servers )
|
||||
THROW_SPEC( std::exception );
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
|
10
dictzip.c
10
dictzip.c
|
@ -349,11 +349,13 @@ static enum DZ_ERRORS dict_read_header( const char *filename,
|
|||
}
|
||||
header->chunks = xmalloc( sizeof( header->chunks[0] )
|
||||
* header->chunkCount );
|
||||
if( header->chunks == 0 ) {
|
||||
return DZ_ERR_NOMEMORY;
|
||||
}
|
||||
if( header->chunks == 0 )
|
||||
{
|
||||
fclose( str );
|
||||
return DZ_ERR_NOMEMORY;
|
||||
}
|
||||
|
||||
for (i = 0; i < header->chunkCount; i++) {
|
||||
for (i = 0; i < header->chunkCount; i++) {
|
||||
header->chunks[i] = getc( str ) << 0;
|
||||
header->chunks[i] |= getc( str ) << 8;
|
||||
}
|
||||
|
|
1
docs/_config.yml
Normal file
1
docs/_config.yml
Normal file
|
@ -0,0 +1 @@
|
|||
theme: jekyll-theme-cayman
|
22
docs/index.md
Normal file
22
docs/index.md
Normal 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 we’ll help you sort it out.
|
128
dsl.cc
128
dsl.cc
|
@ -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" ) )
|
||||
result += "<div class=\"dsl_m\">" + processNodeChildren( node ) + "</div>";
|
||||
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,37 +2055,37 @@ 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" ) )
|
||||
continue; // For now just skip abbreviations
|
||||
if( scanner.getDictionaryName() == U"Abbrev" )
|
||||
continue; // For now just skip abbreviations
|
||||
|
||||
// Building the index
|
||||
initializing.indexingDictionary( Utf8::encode( scanner.getDictionaryName() ) );
|
||||
// Building the index
|
||||
initializing.indexingDictionary( Utf8::encode( scanner.getDictionaryName() ) );
|
||||
|
||||
gdDebug( "Dsl: Building the index for dictionary: %s\n",
|
||||
gd::toQString( scanner.getDictionaryName() ).toUtf8().data() );
|
||||
gdDebug( "Dsl: Building the index for dictionary: %s\n",
|
||||
gd::toQString( scanner.getDictionaryName() ).toUtf8().data() );
|
||||
|
||||
File::Class idx( indexFile, "wb" );
|
||||
File::Class idx( indexFile, "wb" );
|
||||
|
||||
IdxHeader idxHeader;
|
||||
IdxHeader idxHeader;
|
||||
|
||||
memset( &idxHeader, 0, sizeof( idxHeader ) );
|
||||
memset( &idxHeader, 0, sizeof( idxHeader ) );
|
||||
|
||||
// We write a dummy header first. At the end of the process the header
|
||||
// will be rewritten with the right values.
|
||||
// We write a dummy header first. At the end of the process the header
|
||||
// will be rewritten with the right values.
|
||||
|
||||
idx.write( idxHeader );
|
||||
idx.write( idxHeader );
|
||||
|
||||
string dictionaryName = Utf8::encode( scanner.getDictionaryName() );
|
||||
string dictionaryName = Utf8::encode( scanner.getDictionaryName() );
|
||||
|
||||
idx.write( (uint32_t) dictionaryName.size() );
|
||||
idx.write( dictionaryName.data(), dictionaryName.size() );
|
||||
idx.write( (uint32_t)dictionaryName.size() );
|
||||
idx.write( dictionaryName.data(), dictionaryName.size() );
|
||||
|
||||
string soundDictName = Utf8::encode( scanner.getSoundDictionaryName() );
|
||||
if( !soundDictName.empty() )
|
||||
{
|
||||
idxHeader.hasSoundDictionaryName = 1;
|
||||
idx.write( (uint32_t) soundDictName.size() );
|
||||
idx.write( soundDictName.data(), soundDictName.size() );
|
||||
string soundDictName = Utf8::encode( scanner.getSoundDictionaryName() );
|
||||
if( !soundDictName.empty() )
|
||||
{
|
||||
idxHeader.hasSoundDictionaryName = 1;
|
||||
idx.write( (uint32_t)soundDictName.size() );
|
||||
idx.write( soundDictName.data(), soundDictName.size() );
|
||||
}
|
||||
|
||||
idxHeader.dslEncoding = scanner.getEncoding();
|
||||
|
@ -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
2
dsl.hh
|
@ -17,7 +17,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
string const & indicesDir,
|
||||
Dictionary::Initializing &,
|
||||
int maxPictureWidth, unsigned int maxHeadwordSize )
|
||||
THROW_SPEC( std::exception );
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
22
epwing.cc
22
epwing.cc
|
@ -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 )
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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() ) );
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
if ( formatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
#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
38
file.cc
|
@ -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
45
file.hh
|
@ -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() ;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
BIN
flags/folder.png
BIN
flags/folder.png
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.5 KiB |
|
@ -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();
|
||||
|
||||
|
|
8
forvo.cc
8
forvo.cc
|
@ -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;
|
||||
|
||||
|
|
2
forvo.hh
2
forvo.hh
|
@ -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
|
||||
|
|
|
@ -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++ )
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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>
|
||||
|
|
10
gddebug.cc
10
gddebug.cc
|
@ -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() )
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -40,7 +40,7 @@ GermanTable::GermanTable()
|
|||
|
||||
}
|
||||
|
||||
sptr< Dictionary::Class > makeDictionary() THROW_SPEC( std::exception )
|
||||
sptr< Dictionary::Class > makeDictionary()
|
||||
{
|
||||
static GermanTable t;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// Support for German transliteration
|
||||
namespace GermanTranslit {
|
||||
|
||||
sptr< Dictionary::Class > makeDictionary() THROW_SPEC( std::exception );
|
||||
sptr< Dictionary::Class > makeDictionary() ;
|
||||
|
||||
}
|
||||
|
||||
|
|
64
gls.cc
64
gls.cc
|
@ -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;
|
||||
|
||||
out = line.toStdU32String();
|
||||
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
2
gls.hh
|
@ -13,7 +13,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
vector< string > const & fileNames,
|
||||
string const & indicesDir,
|
||||
Dictionary::Initializing & )
|
||||
THROW_SPEC( std::exception );
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
|
161
goldendict.pro
161
goldendict.pro
|
@ -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.
|
||||
|
||||
QM_FILES_INSTALL_PATH = /locale/
|
||||
stl \
|
||||
c++14 \
|
||||
lrelease \
|
||||
embed_translations
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -115,14 +121,13 @@ win32 {
|
|||
}
|
||||
|
||||
unix:!mac {
|
||||
DEFINES += HAVE_X11
|
||||
# This is to keep symbols for backtraces
|
||||
QMAKE_CXXFLAGS += -rdynamic
|
||||
QMAKE_LFLAGS += -rdynamic
|
||||
DEFINES += HAVE_X11
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
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 )
|
||||
|
||||
|
|
|
@ -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
|
|
@ -831,7 +831,7 @@ GreekTable::GreekTable()
|
|||
|
||||
}
|
||||
|
||||
sptr< Dictionary::Class > makeDictionary() THROW_SPEC( std::exception )
|
||||
sptr< Dictionary::Class > makeDictionary()
|
||||
{
|
||||
static GreekTable t;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// Support for Greek transliteration
|
||||
namespace GreekTranslit {
|
||||
|
||||
sptr< Dictionary::Class > makeDictionary() THROW_SPEC( std::exception );
|
||||
sptr< Dictionary::Class > makeDictionary() ;
|
||||
|
||||
}
|
||||
|
||||
|
|
11
groups.cc
11
groups.cc
|
@ -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
|
||||
auto dictMap = Dictionary::dictToMap( dicts );
|
||||
Instances::Group newOrder( order, dictMap, Config::Group() );
|
||||
|
||||
Instances::Group newOrder( order, dicts, Config::Group() );
|
||||
|
||||
if ( ui.dictionaries->getCurrentDictionaries() != newOrder.dictionaries )
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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
211
hotkeys.c
|
@ -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;
|
||||
}
|
14
hotkeys.h
14
hotkeys.h
|
@ -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__
|
22
hotkeys.pro
22
hotkeys.pro
|
@ -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
Loading…
Reference in a new issue