mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-23 16:04:06 +00:00
fix merge conflict
This commit is contained in:
commit
cea97f5727
|
@ -1,28 +1,30 @@
|
|||
# Format Style Options - Created with Clang Power Tools
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: AcrossComments
|
||||
AlignEscapedNewlines: Left
|
||||
AllowAllArgumentsOnNextLine: 'false'
|
||||
AllowShortBlocksOnASingleLine: 'false'
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
BinPackArguments: 'false'
|
||||
BinPackParameters: 'false'
|
||||
BasedOnStyle: LLVM
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Allman
|
||||
BreakConstructorInitializers: AfterColon
|
||||
ColumnLimit: '120'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
|
||||
ConstructorInitializerIndentWidth: '2'
|
||||
ContinuationIndentWidth: '2'
|
||||
MaxEmptyLinesToKeep: '1'
|
||||
ColumnLimit: 120
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth : 2
|
||||
ContinuationIndentWidth: 2
|
||||
MaxEmptyLinesToKeep: 1
|
||||
PointerAlignment: Middle
|
||||
SortIncludes: 'false'
|
||||
SortUsingDeclarations: 'false'
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceBeforeParens: Never
|
||||
SpacesInAngles: 'true'
|
||||
SpacesInParentheses: 'true'
|
||||
SpacesInSquareBrackets: 'true'
|
||||
SpacesInAngles: true
|
||||
SpacesInParentheses: true
|
||||
SpacesInSquareBrackets: true
|
||||
UseTab: Never
|
||||
AlignConsecutiveAssignments: AcrossComments
|
||||
|
||||
...
|
||||
|
|
19
.github/workflows/macos-6.2.yml
vendored
19
.github/workflows/macos-6.2.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [macos-11]
|
||||
qt_ver: [6.2.4,6.3.0]
|
||||
qt_ver: [6.2.4,6.3.1]
|
||||
qt_arch: [clang_64]
|
||||
env:
|
||||
targetName: GoldenDict
|
||||
|
@ -74,6 +74,13 @@ jobs:
|
|||
mv ${targetName}.app ./tmp
|
||||
# --background "installer_background.png"
|
||||
create-dmg --volname "${targetName} Installer" --volicon "icons/macicon.icns" --window-pos 200 120 --window-size 800 400 --icon-size 100 --icon "${targetName}.app" 200 190 --hide-extension "${targetName}.app" --app-drop-link 600 185 --skip-jenkins "${targetName}.dmg" tmp/
|
||||
- name: Generate changelog
|
||||
if: ${{!env.prerelease}}
|
||||
id: changelog1
|
||||
uses: metcalfc/changelog-generator@v3.0.0
|
||||
with:
|
||||
myToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
run: |
|
||||
|
@ -82,6 +89,11 @@ jobs:
|
|||
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=release_hm::$(date +'%y%m%d')"
|
||||
|
||||
- name: changelog
|
||||
if: $${{env.prerelease}}
|
||||
id: changelog2
|
||||
run: |
|
||||
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
|
||||
echo "previousTag : $previousTag"
|
||||
|
||||
|
@ -91,7 +103,7 @@ jobs:
|
|||
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||
CHANGELOG="${CHANGELOG//'\"'/'%22'}"
|
||||
CHANGELOG="${CHANGELOG//"'"/ }"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
# tag 上传Release
|
||||
- name: uploadRelease
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
|
@ -119,4 +131,5 @@ jobs:
|
|||
auto built by github action. use on your on risk:-)
|
||||
|
||||
CHANGES:
|
||||
${{ steps.vars.outputs.COMMIT_SUMMARY }}
|
||||
${{ steps.changelog1.outputs.changelog }}
|
||||
${{ steps.changelog2.outputs.COMMIT_SUMMARY }}
|
||||
|
|
4
.github/workflows/macos-PR-check.yml
vendored
4
.github/workflows/macos-PR-check.yml
vendored
|
@ -1,5 +1,7 @@
|
|||
name: macos-PR-check
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
|
||||
workflow_dispatch:
|
||||
|
|
15
.github/workflows/macos.yml
vendored
15
.github/workflows/macos.yml
vendored
|
@ -75,7 +75,12 @@ jobs:
|
|||
mv ${targetName}.app ./tmp
|
||||
# --background "installer_background.png"
|
||||
create-dmg --volname "${targetName} Installer" --volicon "icons/macicon.icns" --window-pos 200 120 --window-size 800 400 --icon-size 100 --icon "${targetName}.app" 200 190 --hide-extension "${targetName}.app" --app-drop-link 600 185 --skip-jenkins "${targetName}.dmg" tmp/
|
||||
|
||||
- name: Generate changelog
|
||||
if: ${{!env.prerelease}}
|
||||
id: changelog1
|
||||
uses: metcalfc/changelog-generator@v3.0.0
|
||||
with:
|
||||
myToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
|
@ -85,6 +90,11 @@ jobs:
|
|||
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=release_hm::$(date +'%y%m%d')"
|
||||
|
||||
- name: changelog
|
||||
if: $${{env.prerelease}}
|
||||
id: changelog2
|
||||
run: |
|
||||
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
|
||||
echo "previousTag : $previousTag"
|
||||
|
||||
|
@ -122,4 +132,5 @@ jobs:
|
|||
auto built by github action. use on your on risk:-)
|
||||
|
||||
CHANGES:
|
||||
${{ steps.vars.outputs.COMMIT_SUMMARY }}
|
||||
${{ steps.changelog1.outputs.changelog }}
|
||||
${{ steps.changelog2.outputs.COMMIT_SUMMARY }}
|
||||
|
|
44
.github/workflows/ubuntu-6.2.yml
vendored
44
.github/workflows/ubuntu-6.2.yml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
qt_ver: [6.2.4,6.3.0]
|
||||
qt_ver: [6.3.1]
|
||||
qt_arch: [gcc_64]
|
||||
env:
|
||||
version: 22.5.21
|
||||
|
@ -65,30 +65,39 @@ jobs:
|
|||
qmake CONFIG+=release PREFIX=/usr CONFIG+=zim_support CONFIG+=chinese_conversion_support
|
||||
make INSTALL_ROOT=appdir -j`nproc` install; find appdir/
|
||||
|
||||
ls -al appdir
|
||||
#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
|
||||
# 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"
|
||||
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*'
|
||||
wget -c https://github.com/$(wget -q https://github.com/probonopd/go-appimage/releases -O - | grep "appimagetool-.*-x86_64.AppImage" | head -n 1 | cut -d '"' -f 2)
|
||||
chmod +x appimagetool-*.AppImage
|
||||
./appimagetool-*.AppImage -s deploy appdir/usr/share/applications/*.desktop # Bundle EVERYTHING
|
||||
# ./linuxdeploy-x86_64.AppImage --appdir appdir --output appimage --plugin qt -i redist/icons/goldendict.png -d redist/org.goldendict.GoldenDict.desktop
|
||||
|
||||
- name: Generate changelog
|
||||
if: ${{!env.prerelease}}
|
||||
id: changelog1
|
||||
uses: metcalfc/changelog-generator@v3.0.0
|
||||
with:
|
||||
myToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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*)"
|
||||
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
|
||||
echo "::set-output name=release_hm::$(date +'%y%m%d')"
|
||||
echo "::set-output name=appname::$(ls *.AppImage*)"
|
||||
|
||||
- name: changelog
|
||||
if: $${{env.prerelease}}
|
||||
id: changelog2
|
||||
run: |
|
||||
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
|
||||
echo "previousTag : $previousTag"
|
||||
|
||||
|
@ -98,7 +107,7 @@ jobs:
|
|||
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||
CHANGELOG="${CHANGELOG//'\"'/'%22'}"
|
||||
CHANGELOG="${CHANGELOG//"'"/ }"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
- name: uploadRelease
|
||||
# if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
|
@ -126,4 +135,5 @@ jobs:
|
|||
auto built by github action. use on your on risk:-)
|
||||
|
||||
CHANGES:
|
||||
${{ steps.vars.outputs.COMMIT_SUMMARY }}
|
||||
${{ steps.changelog1.outputs.changelog }}
|
||||
${{ steps.changelog2.outputs.COMMIT_SUMMARY }}
|
||||
|
|
4
.github/workflows/ubuntu-PR-check.yml
vendored
4
.github/workflows/ubuntu-PR-check.yml
vendored
|
@ -1,5 +1,7 @@
|
|||
name: Ubuntu-PR-check
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
|
||||
workflow_dispatch:
|
||||
|
|
21
.github/workflows/ubuntu.yml
vendored
21
.github/workflows/ubuntu.yml
vendored
|
@ -77,15 +77,27 @@ jobs:
|
|||
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
|
||||
|
||||
- name: Generate changelog
|
||||
if: ${{!env.prerelease}}
|
||||
id: changelog1
|
||||
uses: metcalfc/changelog-generator@v3.0.0
|
||||
with:
|
||||
myToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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*)"
|
||||
echo "::set-output name=release_time_clock::$(date +'%H:%M:%S')"
|
||||
echo "::set-output name=release_hm::$(date +'%y%m%d')"
|
||||
echo "::set-output name=appname::$(ls *.AppImage*)"
|
||||
|
||||
- name: changelog
|
||||
if: $${{env.prerelease}}
|
||||
id: changelog2
|
||||
run: |
|
||||
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
|
||||
echo "previousTag : $previousTag"
|
||||
|
||||
|
@ -95,7 +107,7 @@ jobs:
|
|||
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||
CHANGELOG="${CHANGELOG//'\"'/'%22'}"
|
||||
CHANGELOG="${CHANGELOG//"'"/ }"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
- name: uploadRelease
|
||||
# if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
|
@ -123,4 +135,5 @@ jobs:
|
|||
auto built by github action. use on your on risk:-)
|
||||
|
||||
CHANGES:
|
||||
${{ steps.vars.outputs.COMMIT_SUMMARY }}
|
||||
${{ steps.changelog1.outputs.changelog }}
|
||||
${{ steps.changelog2.outputs.COMMIT_SUMMARY }}
|
||||
|
|
26
.github/workflows/windows-6.2.yml
vendored
26
.github/workflows/windows-6.2.yml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [windows-2019]
|
||||
qt_ver: [6.2.4,6.3.0]
|
||||
qt_ver: [6.2.4,6.3.1]
|
||||
qt_arch: [win64_msvc2019_64]
|
||||
env:
|
||||
targetName: GoldenDict.exe
|
||||
|
@ -52,15 +52,28 @@ jobs:
|
|||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate changelog
|
||||
if: ${{!env.prerelease}}
|
||||
id: changelog1
|
||||
uses: metcalfc/changelog-generator@v3.0.0
|
||||
with:
|
||||
myToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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')"
|
||||
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=release_hm::$(date +'%y%m%d')"
|
||||
|
||||
- name: changelog
|
||||
if: $${{env.prerelease}}
|
||||
id: changelog2
|
||||
shell: bash
|
||||
run: |
|
||||
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
|
||||
echo "previousTag : $previousTag"
|
||||
|
||||
|
@ -70,7 +83,7 @@ jobs:
|
|||
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||
CHANGELOG="${CHANGELOG//'\"'/'%22'}"
|
||||
CHANGELOG="${CHANGELOG//"'"/ }"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
|
||||
# # msvc编译
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
@ -128,6 +141,11 @@ jobs:
|
|||
Qt6.X(Universal Build)
|
||||
Qt5.15.2(Intel Kind)
|
||||
auto built by github action. use on your on risk:-)
|
||||
|
||||
CHANGES:
|
||||
${{ steps.changelog1.outputs.changelog }}
|
||||
${{ steps.changelog2.outputs.COMMIT_SUMMARY }}
|
||||
|
||||
- name: upload goldendict.exe only
|
||||
# if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
|
|
4
.github/workflows/windows-PR-check.yml
vendored
4
.github/workflows/windows-PR-check.yml
vendored
|
@ -1,5 +1,7 @@
|
|||
name: Windows-PR-check
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
|
||||
workflow_dispatch:
|
||||
|
|
22
.github/workflows/windows.yml
vendored
22
.github/workflows/windows.yml
vendored
|
@ -54,15 +54,28 @@ jobs:
|
|||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate changelog
|
||||
if: ${{!env.prerelease}}
|
||||
id: changelog1
|
||||
uses: metcalfc/changelog-generator@v3.0.0
|
||||
with:
|
||||
myToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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')"
|
||||
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=release_hm::$(date +'%y%m%d')"
|
||||
|
||||
- name: changelog
|
||||
if: $${{env.prerelease}}
|
||||
id: changelog2
|
||||
shell: bash
|
||||
run: |
|
||||
previousTag=$(git tag --sort=-creatordate | sed -n 2p)
|
||||
echo "previousTag : $previousTag"
|
||||
|
||||
|
@ -72,7 +85,7 @@ jobs:
|
|||
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||
CHANGELOG="${CHANGELOG//'\"'/'%22'}"
|
||||
CHANGELOG="${CHANGELOG//"'"/ }"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
echo "::set-output name=COMMIT_SUMMARY::$(echo "$CHANGELOG")"
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
# msvc编译
|
||||
- name: msvc-build goldendict
|
||||
|
@ -127,7 +140,8 @@ jobs:
|
|||
auto built by github action. use on your on risk:-)
|
||||
|
||||
CHANGES:
|
||||
${{ steps.vars.outputs.COMMIT_SUMMARY }}
|
||||
${{ steps.changelog1.outputs.changelog }}
|
||||
${{ steps.changelog2.outputs.COMMIT_SUMMARY }}
|
||||
- name: upload goldendict.exe only
|
||||
# if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
|
|
11
CHANGES.md
11
CHANGES.md
|
@ -3,6 +3,17 @@
|
|||
## Until to now
|
||||
|
||||
- **CLEANING OLD/USELESS CODE**
|
||||
- remove Runnable Class in dsl, zim , epwing etc files.
|
||||
|
||||
- add "send to anki"
|
||||
- right context menu actions, remove nonsense character like `OBJ`,punctuation etc.
|
||||
- epwing remove duplicate entries when index.
|
||||
- replace throw() with noexcept
|
||||
- replace string(***constData) with toStdString
|
||||
- add built-in support for entry links in javascript files
|
||||
|
||||
|
||||
## Until 2022-5-21
|
||||
- fix a zim about:blank#block [issue](https://github.com/goldendict/goldendict/issues/1472#issuecomment-1086776611)
|
||||
- add fallback font family configuration for dictionary through preference dialog.
|
||||
- fix mdx (compact html) display error on the last item.
|
||||
|
|
16
aard.cc
16
aard.cc
|
@ -239,16 +239,16 @@ class AardDictionary: public BtreeIndexing::BtreeDictionary
|
|||
|
||||
~AardDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -284,7 +284,7 @@ class AardDictionary: public BtreeIndexing::BtreeDictionary
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -338,7 +338,7 @@ AardDictionary::~AardDictionary()
|
|||
df.close();
|
||||
}
|
||||
|
||||
void AardDictionary::loadIcon() throw()
|
||||
void AardDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
@ -429,7 +429,7 @@ void AardDictionary::loadArticle( quint32 address,
|
|||
|
||||
while( 1 )
|
||||
{
|
||||
articleText = string( QObject::tr( "Article loading error" ).toUtf8().constData() );
|
||||
articleText = QObject::tr( "Article loading error" ).toStdString();
|
||||
try
|
||||
{
|
||||
Mutex::Lock _( aardMutex );
|
||||
|
@ -521,7 +521,7 @@ void AardDictionary::loadArticle( quint32 address,
|
|||
articleText = convert( articleText );
|
||||
}
|
||||
else
|
||||
articleText = string( QObject::tr( "Article decoding error" ).toUtf8().constData() );
|
||||
articleText = QObject::tr( "Article decoding error" ).toStdString();
|
||||
|
||||
// See Issue #271: A mechanism to clean-up invalid HTML cards.
|
||||
string cleaner = "</font>""</font>""</font>""</font>""</font>""</font>"
|
||||
|
|
6
about.cc
6
about.cc
|
@ -23,10 +23,8 @@ About::About( QWidget * parent ): QDialog( parent )
|
|||
ui.version->setText( version );
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
QString compilerVersion = QString( "Visual C++ %1.%2.%3" )
|
||||
.arg( GD_CXX_MSVC_MAJOR )
|
||||
.arg( GD_CXX_MSVC_MINOR )
|
||||
.arg( GD_CXX_MSVC_BUILD );
|
||||
QString compilerVersion = QString( "Visual C++ Compiler: %1" )
|
||||
.arg( _MSC_FULL_VER );
|
||||
#elif defined (__clang__) && defined (__clang_version__)
|
||||
QString compilerVersion = QLatin1String( "Clang " ) + QLatin1String( __clang_version__ );
|
||||
#else
|
||||
|
|
14
about.hh
14
about.hh
|
@ -7,20 +7,6 @@
|
|||
#include "ui_about.h"
|
||||
#include <QDialog>
|
||||
|
||||
// Microsoft Visual C++ version
|
||||
#if defined (_MSC_VER)
|
||||
// how many digits does the build number have?
|
||||
# if _MSC_FULL_VER / 10000 == _MSC_VER
|
||||
# define GD_CXX_MSVC_BUILD (_MSC_FULL_VER % 10000) // four digits
|
||||
# elif _MSC_FULL_VER / 100000 == _MSC_VER
|
||||
# define GD_CXX_MSVC_BUILD (_MSC_FULL_VER % 100000) // five digits
|
||||
# else
|
||||
# define GD_CXX_MSVC_BUILD 0
|
||||
# endif
|
||||
# define GD_CXX_MSVC_MAJOR (_MSC_VER/100-6)
|
||||
# define GD_CXX_MSVC_MINOR (_MSC_VER%100)
|
||||
#endif
|
||||
|
||||
class About: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
85
ankiconnector.cpp
Normal file
85
ankiconnector.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include "ankiconnector.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include "utils.hh"
|
||||
AnkiConnector::AnkiConnector( QObject * parent, Config::Class const & _cfg ) : QObject{ parent }, cfg( _cfg )
|
||||
{
|
||||
mgr = new QNetworkAccessManager( this );
|
||||
connect( mgr, &QNetworkAccessManager::finished, this, &AnkiConnector::finishedSlot );
|
||||
}
|
||||
|
||||
void AnkiConnector::sendToAnki( QString const & word, QString const & text )
|
||||
{
|
||||
//for simplicity. maybe use QJsonDocument in future?
|
||||
QString postTemplate = QString( "{"
|
||||
"\"action\": \"addNote\","
|
||||
"\"version\": 6,"
|
||||
"\"params\": {"
|
||||
" \"note\": {"
|
||||
" \"deckName\": \"%1\","
|
||||
" \"modelName\": \"%2\","
|
||||
" \"fields\":%3,"
|
||||
" \"options\": {"
|
||||
" \"allowDuplicate\": true"
|
||||
" },"
|
||||
" \"tags\": []"
|
||||
"}"
|
||||
"}"
|
||||
"}"
|
||||
"" );
|
||||
|
||||
QJsonObject fields;
|
||||
fields.insert( "Front", word );
|
||||
fields.insert( "Back", text );
|
||||
|
||||
QString postData = postTemplate.arg( cfg.preferences.ankiConnectServer.deck,
|
||||
cfg.preferences.ankiConnectServer.model,
|
||||
Utils::json2String( fields ) );
|
||||
|
||||
// qDebug().noquote() << postData;
|
||||
QUrl url;
|
||||
url.setScheme( "http" );
|
||||
url.setHost( cfg.preferences.ankiConnectServer.host );
|
||||
url.setPort( cfg.preferences.ankiConnectServer.port );
|
||||
QNetworkRequest request( url );
|
||||
request.setTransferTimeout( 3000 );
|
||||
// request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy );
|
||||
request.setHeader( QNetworkRequest::ContentTypeHeader, "applicaion/json" );
|
||||
auto reply = mgr->post( request, postData.toUtf8() );
|
||||
connect( reply,
|
||||
&QNetworkReply::errorOccurred,
|
||||
this,
|
||||
[ this ]( QNetworkReply::NetworkError e )
|
||||
{
|
||||
qWarning() << e;
|
||||
emit this->errorText( tr( "anki: post to anki failed" ) );
|
||||
} );
|
||||
}
|
||||
|
||||
void AnkiConnector::finishedSlot( QNetworkReply * reply )
|
||||
{
|
||||
if( reply->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QByteArray bytes = reply->readAll();
|
||||
QJsonDocument json = QJsonDocument::fromJson( bytes );
|
||||
auto obj = json.object();
|
||||
if( obj.size() != 2 || !obj.contains( "error" ) || !obj.contains( "result" ) ||
|
||||
obj[ "result" ].toString().isEmpty() )
|
||||
{
|
||||
emit errorText( QObject::tr( "anki: post to anki failed" ) );
|
||||
}
|
||||
QString result = obj[ "result" ].toString();
|
||||
|
||||
qDebug() << "anki result:" << result;
|
||||
|
||||
emit errorText( tr( "anki: post to anki success" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "anki connect error" << reply->errorString();
|
||||
emit errorText( "anki:" + reply->errorString() );
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
28
ankiconnector.h
Normal file
28
ankiconnector.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef ANKICONNECTOR_H
|
||||
#define ANKICONNECTOR_H
|
||||
|
||||
#include "config.hh"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QObject>
|
||||
|
||||
class AnkiConnector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AnkiConnector( QObject * parent, Config::Class const & cfg );
|
||||
|
||||
void sendToAnki( QString const & word, QString const & text );
|
||||
|
||||
private:
|
||||
QNetworkAccessManager * mgr;
|
||||
Config::Class const & cfg;
|
||||
public :
|
||||
signals:
|
||||
void errorText( QString const & );
|
||||
private slots:
|
||||
void finishedSlot(QNetworkReply * reply);
|
||||
};
|
||||
|
||||
#endif // ANKICONNECTOR_H
|
|
@ -95,7 +95,7 @@ body
|
|||
|
||||
.gddictnamebodyseparator
|
||||
{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
clear: both;
|
||||
border-top: 1px solid #92b0dd;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
|
|
@ -24,24 +24,19 @@ a:hover
|
|||
background: white;
|
||||
}
|
||||
|
||||
/* Dictionary's name heading */
|
||||
.gddictname
|
||||
{
|
||||
border: 1px dotted black; padding: 0.2em; padding-left: 0.5em;
|
||||
margin-top: 1.2em; margin-bottom: 0.1em; font-weight: bold; font-size: 14px;
|
||||
background: #87CEEB;
|
||||
}
|
||||
|
||||
/* The 'From ' string which preceeds dictionary name in the heading */
|
||||
.gdfromprefix
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Dictionary's name heading */
|
||||
.gddictname
|
||||
{
|
||||
padding: 0.2em; padding-left: 0.5em;
|
||||
margin-bottom: 0.1em;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
|
||||
float: right;
|
||||
border: 1px solid white;
|
||||
margin-top: 7px;
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
/******** Global, non-dictionary-specific classes ***********/
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
background: #fefdeb;
|
||||
font-family: Tahoma, Verdana, "Lucida Sans Unicode", sans-serif;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* This stylesheet is used to highligh current selection when doing a search.
|
||||
|
@ -38,6 +42,16 @@ pre
|
|||
/*background: #ffffdd;*/
|
||||
}
|
||||
|
||||
.gddicttitle
|
||||
{
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.gddictnamebodyseparator
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* The 'From ' string which precedes dictionary name in the heading */
|
||||
.gdfromprefix
|
||||
{
|
||||
|
@ -55,8 +69,8 @@ pre
|
|||
background: #fefdeb;
|
||||
/*fix for invalid blg*/
|
||||
font-style:normal;
|
||||
content-visibility:auto;
|
||||
contain-intrinsic-size:400px;
|
||||
content-visibility: auto;
|
||||
contain-intrinsic-size: 600px;
|
||||
}
|
||||
|
||||
/* CSS trick to prevent the floating elements to overflow
|
||||
|
@ -522,7 +536,7 @@ div.xdxf
|
|||
/************* MDict dictionaries **************/
|
||||
.mdict
|
||||
{
|
||||
margin-top: 1em;
|
||||
|
||||
}
|
||||
|
||||
.mdict a[name]
|
||||
|
@ -914,7 +928,6 @@ div.xdxf
|
|||
left: 0px;
|
||||
width: 0px;
|
||||
background-color: white;
|
||||
background-color: Window;
|
||||
border-style: solid;
|
||||
border-color: #AAAAAA;
|
||||
border-width: 1px;
|
||||
|
@ -934,9 +947,7 @@ div.xdxf
|
|||
.mwiki td.os-suggest-result, .mwiki td.os-suggest-result-hl {
|
||||
white-space: nowrap;
|
||||
background-color: white;
|
||||
background-color: Window;
|
||||
color: black;
|
||||
color: WindowText;
|
||||
padding: 2px;
|
||||
}
|
||||
.mwiki td.os-suggest-result-hl,
|
||||
|
@ -944,12 +955,6 @@ div.xdxf
|
|||
background-color: #4C59A6;
|
||||
color: white;
|
||||
}
|
||||
.mwiki td.os-suggest-result-hl {
|
||||
/* System colors are misimplemented in Safari 3.0 and earlier,
|
||||
making highlighted text illegible... */
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
.mwiki .os-suggest-toggle {
|
||||
position: relative;
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
#if (QT_VERSION > QT_VERSION_CHECK(6,0,0))
|
||||
#include <QWebEngineContextMenuRequest>
|
||||
#endif
|
||||
ArticleInspector::ArticleInspector( QWidget * parent ) : QWidget( parent, Qt::WindowType::Window )
|
||||
ArticleInspector::ArticleInspector( QWidget * parent ) : QWidget( parent, Qt::WindowType::Window ),firstTimeOpened(false)
|
||||
{
|
||||
setWindowTitle(tr("Inspect"));
|
||||
setAttribute( Qt::WidgetAttribute::WA_DeleteOnClose, false );
|
||||
QVBoxLayout * v = new QVBoxLayout( this );
|
||||
v->setSpacing( 0 );
|
||||
v->setContentsMargins( 0, 0, 0, 0 );
|
||||
inspectView = new QWebEngineView( this );
|
||||
v->addWidget( inspectView );
|
||||
viewContainer = new QWebEngineView( this );
|
||||
v->addWidget( viewContainer );
|
||||
|
||||
resize(800,600);
|
||||
}
|
||||
|
@ -19,22 +19,26 @@ ArticleInspector::ArticleInspector( QWidget * parent ) : QWidget( parent, Qt::Wi
|
|||
void ArticleInspector::setInspectPage( QWebEngineView * view )
|
||||
{
|
||||
auto page=view->page();
|
||||
this->inspectedPage = page;
|
||||
page->setDevToolsPage( inspectView->page() );
|
||||
viewContainer->page()->setInspectedPage(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() )
|
||||
if( view->lastContextMenuRequest() && firstTimeOpened )
|
||||
{
|
||||
page->triggerAction( QWebEnginePage::InspectElement );
|
||||
}
|
||||
if( !firstTimeOpened )
|
||||
{
|
||||
firstTimeOpened = true;
|
||||
}
|
||||
#else
|
||||
page->triggerAction( QWebEnginePage::InspectElement );
|
||||
#endif
|
||||
|
||||
raise();
|
||||
show();
|
||||
}
|
||||
|
||||
void ArticleInspector::closeEvent( QCloseEvent * )
|
||||
{
|
||||
inspectedPage->setDevToolsPage( nullptr );
|
||||
viewContainer->page()->setInspectedPage(nullptr);
|
||||
}
|
||||
|
|
|
@ -9,14 +9,15 @@
|
|||
class ArticleInspector : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
QWebEngineView * inspectView = nullptr;
|
||||
QWebEnginePage * inspectedPage = nullptr;
|
||||
QWebEngineView * viewContainer = nullptr;
|
||||
public:
|
||||
ArticleInspector( QWidget * parent = nullptr );
|
||||
|
||||
void setInspectPage( QWebEngineView * view);
|
||||
private:
|
||||
|
||||
//used to record if the devtool was first time opened.
|
||||
//if right click on the webpage and open inspect page on the first time ,the application has great possiblity to hang forever.
|
||||
bool firstTimeOpened;
|
||||
virtual void closeEvent( QCloseEvent * );
|
||||
};
|
||||
|
||||
|
|
|
@ -465,7 +465,7 @@ void ArticleRequest::altSearchFinished()
|
|||
if ( altSearches.empty() )
|
||||
{
|
||||
#ifdef QT_DEBUG
|
||||
qDebug( "alts finished\n" );
|
||||
qDebug( "alts finished" );
|
||||
#endif
|
||||
|
||||
// They all've finished! Now we can look up bodies
|
||||
|
@ -534,7 +534,7 @@ void ArticleRequest::bodyFinished()
|
|||
if ( bodyDone )
|
||||
return;
|
||||
|
||||
GD_DPRINTF( "some body finished\n" );
|
||||
GD_DPRINTF( "some body finished" );
|
||||
|
||||
bool wasUpdated = false;
|
||||
|
||||
|
@ -546,7 +546,7 @@ void ArticleRequest::bodyFinished()
|
|||
{
|
||||
// Good
|
||||
|
||||
GD_DPRINTF( "one finished.\n" );
|
||||
GD_DPRINTF( "one finished." );
|
||||
|
||||
Dictionary::DataRequest & req = *bodyRequests.front();
|
||||
|
||||
|
@ -672,13 +672,13 @@ void ArticleRequest::bodyFinished()
|
|||
|
||||
foundAnyDefinitions = true;
|
||||
}
|
||||
GD_DPRINTF( "erasing..\n" );
|
||||
GD_DPRINTF( "erasing.." );
|
||||
bodyRequests.pop_front();
|
||||
GD_DPRINTF( "erase done..\n" );
|
||||
GD_DPRINTF( "erase done.." );
|
||||
}
|
||||
else
|
||||
{
|
||||
GD_DPRINTF( "one not finished.\n" );
|
||||
GD_DPRINTF( "one not finished." );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "gddebug.hh"
|
||||
#include "utils.hh"
|
||||
#include <QNetworkAccessManager>
|
||||
#include "globalbroadcaster.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
@ -131,22 +132,11 @@ using std::string;
|
|||
emit errorOccurred( code );
|
||||
}
|
||||
|
||||
// void AllowFrameReply::readDataFromBase()
|
||||
// {
|
||||
//// QByteArray data;
|
||||
//// data.resize( baseReply->bytesAvailable() );
|
||||
//// baseReply->read( data.data(), data.size() );
|
||||
//// buffer += data;
|
||||
// emit readyRead();
|
||||
// }
|
||||
|
||||
qint64 AllowFrameReply::readData( char * data, qint64 maxSize )
|
||||
{
|
||||
auto bytesAvailable= baseReply->bytesAvailable();
|
||||
qint64 size = qMin( maxSize, bytesAvailable );
|
||||
baseReply->read( data, size );
|
||||
// memcpy( data, buffer.data(), size );
|
||||
// buffer.remove( 0, size );
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -209,11 +199,8 @@ QNetworkReply * ArticleNetworkAccessManager::getArticleReply( QNetworkRequest co
|
|||
|
||||
QUrl refererUrl = QUrl::fromEncoded( referer );
|
||||
|
||||
//GD_DPRINTF( "Considering %s vs %s\n", getHostBase( req.url() ).toUtf8().data(),
|
||||
// getHostBase( refererUrl ).toUtf8().data() );
|
||||
|
||||
if ( !url.host().endsWith( refererUrl.host() ) &&
|
||||
getHostBase( url ) != getHostBase( refererUrl ) && !url.scheme().startsWith("data") )
|
||||
getHostBaseFromUrl( url ) != getHostBaseFromUrl( refererUrl ) && !url.scheme().startsWith("data") )
|
||||
{
|
||||
gdWarning( "Blocking element \"%s\" due to not same domain", url.toEncoded().data() );
|
||||
|
||||
|
@ -265,9 +252,9 @@ QNetworkReply * ArticleNetworkAccessManager::getArticleReply( QNetworkRequest co
|
|||
sptr< Dictionary::DataRequest > ArticleNetworkAccessManager::getResource(
|
||||
QUrl const & url, QString & contentType )
|
||||
{
|
||||
GD_DPRINTF( "getResource: %ls\n", url.toString().toStdWString().c_str() );
|
||||
GD_DPRINTF( "scheme: %ls\n", url.scheme().toStdWString().c_str() );
|
||||
GD_DPRINTF( "host: %ls\n", url.host().toStdWString().c_str() );
|
||||
GD_DPRINTF( "getResource: %ls", url.toString().toStdWString().c_str() );
|
||||
GD_DPRINTF( "scheme: %ls", url.scheme().toStdWString().c_str() );
|
||||
GD_DPRINTF( "host: %ls", url.host().toStdWString().c_str() );
|
||||
|
||||
if ( url.scheme() == "gdlookup" )
|
||||
{
|
||||
|
@ -460,7 +447,7 @@ qint64 ArticleResourceReply::readData( char * out, qint64 maxSize )
|
|||
qint64 left = avail - alreadyRead;
|
||||
|
||||
qint64 toRead = maxSize < left ? maxSize : left;
|
||||
GD_DPRINTF( "====reading %d bytes\n", (int)toRead );
|
||||
GD_DPRINTF( "====reading %d bytes", (int)toRead );
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -468,7 +455,7 @@ qint64 ArticleResourceReply::readData( char * out, qint64 maxSize )
|
|||
}
|
||||
catch( std::exception & e )
|
||||
{
|
||||
qWarning( "getDataSlice error: %s\n", e.what() );
|
||||
qWarning( "getDataSlice error: %s", e.what() );
|
||||
}
|
||||
|
||||
alreadyRead += toRead;
|
||||
|
@ -526,6 +513,16 @@ void LocalSchemeHandler::requestStarted(QWebEngineUrlRequestJob *requestJob)
|
|||
QNetworkRequest request;
|
||||
request.setUrl( url );
|
||||
|
||||
//all the url reached here must be either gdlookup or bword scheme.
|
||||
auto [valid, word] = Utils::Url::getQueryWord( url );
|
||||
// or the condition can be (!queryWord.first || word.isEmpty())
|
||||
// ( queryWord.first && word.isEmpty() ) is only part of the above condition.
|
||||
if( valid && word.isEmpty() )
|
||||
{
|
||||
// invalid gdlookup url.
|
||||
return;
|
||||
}
|
||||
|
||||
QNetworkReply * reply = this->mManager.getArticleReply( request );
|
||||
connect( reply, &QNetworkReply::finished, requestJob, [ = ]() { requestJob->reply( "text/html", reply ); } );
|
||||
connect( requestJob, &QObject::destroyed, reply, &QObject::deleteLater );
|
||||
|
|
268
articleview.cc
268
articleview.cc
|
@ -325,6 +325,7 @@ ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm, Au
|
|||
settings->defaultSettings()->setAttribute( QWebEngineSettings::PluginsEnabled, cfg.preferences.enableWebPlugins );
|
||||
settings->defaultSettings()->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, false );
|
||||
settings->defaultSettings()->setAttribute( QWebEngineSettings::JavascriptCanAccessClipboard, true );
|
||||
settings->defaultSettings()->setAttribute( QWebEngineSettings::PrintElementBackgrounds, false );
|
||||
#else
|
||||
settings->setAttribute( QWebEngineSettings::LocalContentCanAccessRemoteUrls, true );
|
||||
settings->setAttribute( QWebEngineSettings::LocalContentCanAccessFileUrls, true );
|
||||
|
@ -332,6 +333,7 @@ ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm, Au
|
|||
settings->setAttribute( QWebEngineSettings::PluginsEnabled, cfg.preferences.enableWebPlugins );
|
||||
settings->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, false );
|
||||
settings->setAttribute( QWebEngineSettings::JavascriptCanAccessClipboard, true );
|
||||
settings->setAttribute( QWebEngineSettings::PrintElementBackgrounds, false );
|
||||
#endif
|
||||
|
||||
expandOptionalParts = cfg.preferences.alwaysExpandOptionalParts;
|
||||
|
@ -348,6 +350,11 @@ ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm, Au
|
|||
channel = new QWebChannel(ui.definition->page());
|
||||
agent = new ArticleViewAgent(this);
|
||||
attachWebChannelToHtml();
|
||||
ankiConnector = new AnkiConnector( this, cfg );
|
||||
connect( ankiConnector,
|
||||
&AnkiConnector::errorText,
|
||||
this,
|
||||
[ this ]( QString const & errorText ) { emit statusBarMessage( errorText ); } );
|
||||
}
|
||||
|
||||
// explicitly report the minimum size, to avoid
|
||||
|
@ -395,6 +402,12 @@ void ArticleView::showDefinition( Config::InputPhrase const & phrase, unsigned g
|
|||
if ( scrollTo.size() )
|
||||
Utils::Url::addQueryItem( req, "scrollto", scrollTo );
|
||||
|
||||
if( delayedHighlightText.size() )
|
||||
{
|
||||
Utils::Url::addQueryItem( req, "regexp", delayedHighlightText );
|
||||
delayedHighlightText.clear();
|
||||
}
|
||||
|
||||
Contexts::Iterator pos = contexts.find( "gdanchor" );
|
||||
if( pos != contexts.end() )
|
||||
{
|
||||
|
@ -422,8 +435,7 @@ void ArticleView::showDefinition( Config::InputPhrase const & phrase, unsigned g
|
|||
if ( mutedDicts.size() )
|
||||
Utils::Url::addQueryItem( req, "muted", mutedDicts );
|
||||
|
||||
// Update both histories (pages history and headwords history)
|
||||
saveHistoryUserData();
|
||||
// Update headwords history
|
||||
emit sendWordToHistory( phrase.phrase );
|
||||
|
||||
// Any search opened is probably irrelevant now
|
||||
|
@ -434,7 +446,7 @@ void ArticleView::showDefinition( Config::InputPhrase const & phrase, unsigned g
|
|||
|
||||
emit setExpandMode( expandOptionalParts );
|
||||
|
||||
ui.definition->load( req );
|
||||
load( req );
|
||||
|
||||
//QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
ui.definition->setCursor( Qt::WaitCursor );
|
||||
|
@ -472,8 +484,7 @@ void ArticleView::showDefinition( QString const & word, QStringList const & dict
|
|||
if( ignoreDiacritics )
|
||||
Utils::Url::addQueryItem( req, "ignore_diacritics", "1" );
|
||||
|
||||
// Update both histories (pages history and headwords history)
|
||||
saveHistoryUserData();
|
||||
// Update headwords history
|
||||
emit sendWordToHistory( word );
|
||||
|
||||
// Any search opened is probably irrelevant now
|
||||
|
@ -484,11 +495,15 @@ void ArticleView::showDefinition( QString const & word, QStringList const & dict
|
|||
|
||||
emit setExpandMode( expandOptionalParts );
|
||||
|
||||
ui.definition->load( req );
|
||||
load( req );
|
||||
|
||||
ui.definition->setCursor( Qt::WaitCursor );
|
||||
}
|
||||
|
||||
void ArticleView::sendToAnki(QString const & word, QString const & text ){
|
||||
ankiConnector->sendToAnki(word,text);
|
||||
}
|
||||
|
||||
void ArticleView::showAnticipation()
|
||||
{
|
||||
ui.definition->setHtml( "" );
|
||||
|
@ -520,13 +535,6 @@ void ArticleView::loadFinished( bool result )
|
|||
// Expand collapsed article if only one loaded
|
||||
ui.definition->page()->runJavaScript( QString( "gdCheckArticlesNumber();" ) );
|
||||
|
||||
// Jump to current article after page reloading
|
||||
if( !articleToJump.isEmpty() )
|
||||
{
|
||||
setCurrentArticle( articleToJump, true );
|
||||
articleToJump.clear();
|
||||
}
|
||||
|
||||
if( !Utils::Url::queryItemValue( url, "gdanchor" ).isEmpty() )
|
||||
{
|
||||
QString anchor = QUrl::fromPercentEncoding( Utils::Url::encodedQueryItemValue( url, "gdanchor" ) );
|
||||
|
@ -641,18 +649,18 @@ void ArticleView::jumpToDictionary( QString const & id, bool force )
|
|||
}
|
||||
}
|
||||
|
||||
void ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
|
||||
bool ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
|
||||
{
|
||||
if ( !isScrollTo( id ) )
|
||||
return; // Incorrect id
|
||||
return false; // Incorrect id
|
||||
|
||||
if ( !ui.definition->isVisible() )
|
||||
return; // No action on background page, scrollIntoView there don't work
|
||||
return false; // No action on background page, scrollIntoView there don't work
|
||||
|
||||
if(moveToIt){
|
||||
QString dictId = id.mid( 7 );
|
||||
if( dictId.isEmpty() )
|
||||
return;
|
||||
return false;
|
||||
QString script = QString( "var elem=document.getElementById('%1'); "
|
||||
"if(elem!=undefined){elem.scrollIntoView(true);} gdMakeArticleActive('%2',true);" )
|
||||
.arg( id, dictId );
|
||||
|
@ -660,6 +668,7 @@ void ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
|
|||
ui.definition->page()->runJavaScript( script );
|
||||
setActiveArticleId( dictId );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArticleView::selectCurrentArticle()
|
||||
|
@ -696,45 +705,26 @@ void ArticleView::tryMangleWebsiteClickedUrl( QUrl & url, Contexts & contexts )
|
|||
{
|
||||
if( framed )
|
||||
{
|
||||
// QVariant result = runJavaScriptSync( ui.definition->page(), "gdLastUrlText" );
|
||||
QVariant result;
|
||||
|
||||
if( result.type() == QVariant::String )
|
||||
{
|
||||
// Looks this way
|
||||
contexts[ dictionaryIdFromScrollTo( ca ) ] = QString::fromLatin1( url.toEncoded() );
|
||||
|
||||
QUrl target;
|
||||
|
||||
QString queryWord = result.toString();
|
||||
|
||||
// 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 );
|
||||
|
||||
url = target;
|
||||
}
|
||||
// no need to translate website internal url to gd builtin url
|
||||
// and lack the formulation to convert them.
|
||||
qDebug() << "in the website with url:" << url;
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleView::updateCurrentArticleFromCurrentFrame( QWebEnginePage * frame ,QPoint * point)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ArticleView::saveHistoryUserData()
|
||||
{
|
||||
ui.definition->setProperty("sx", ui.definition->page()->scrollPosition().x());
|
||||
ui.definition->setProperty("sy", ui.definition->page()->scrollPosition().y());
|
||||
}
|
||||
|
||||
void ArticleView::load( QUrl const & url )
|
||||
{
|
||||
saveHistoryUserData();
|
||||
ui.definition->load( url );
|
||||
}
|
||||
|
||||
void ArticleView::cleanupTemp()
|
||||
{
|
||||
QSet< QString >::iterator it = desktopOpenedTempFiles.begin();
|
||||
|
@ -1088,8 +1078,6 @@ void ArticleView::linkClicked( QUrl const & url_ )
|
|||
if( kmod & Qt::AltModifier )
|
||||
return;
|
||||
|
||||
updateCurrentArticleFromCurrentFrame();
|
||||
|
||||
QUrl url( url_ );
|
||||
Contexts contexts;
|
||||
|
||||
|
@ -1122,22 +1110,29 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
|
|||
audioPlayer->stop();
|
||||
qDebug() << "open link url:" << url;
|
||||
|
||||
auto [valid, word] = Utils::Url::getQueryWord( url );
|
||||
if( valid && word.isEmpty() )
|
||||
{
|
||||
// invalid gdlookup url.
|
||||
return;
|
||||
}
|
||||
|
||||
Contexts contexts( contexts_ );
|
||||
|
||||
if( url.scheme().compare( "gdpicture" ) == 0 )
|
||||
ui.definition->load( url );
|
||||
load( url );
|
||||
else
|
||||
if ( url.scheme().compare( "bword" ) == 0 )
|
||||
if ( url.scheme().compare( "bword" ) == 0 || url.scheme().compare( "entry" ) == 0 )
|
||||
{
|
||||
if( Utils::Url::hasQueryItem( ref, "dictionaries" ) )
|
||||
{
|
||||
QStringList dictsList = Utils::Url::queryItemValue( ref, "dictionaries" )
|
||||
.split( ",", Qt::SkipEmptyParts );
|
||||
|
||||
showDefinition( url.path(), dictsList, QRegExp(), getGroup( ref ), false );
|
||||
showDefinition( word, dictsList, QRegExp(), getGroup( ref ), false );
|
||||
}
|
||||
else
|
||||
showDefinition( url.path(),
|
||||
showDefinition( word,
|
||||
getGroup( ref ), scrollTo, contexts );
|
||||
}
|
||||
else
|
||||
|
@ -1160,16 +1155,6 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
|
|||
return;
|
||||
}
|
||||
|
||||
QString word;
|
||||
|
||||
if( Utils::Url::hasQueryItem( url, "word" ) )
|
||||
{
|
||||
word=Utils::Url::queryItemValue (url,"word");
|
||||
}
|
||||
else{
|
||||
word=url.path ().mid (1);
|
||||
}
|
||||
|
||||
QString newScrollTo( scrollTo );
|
||||
if( Utils::Url::hasQueryItem( url, "dict" ) )
|
||||
{
|
||||
|
@ -1583,9 +1568,7 @@ void ArticleView::updateMutedContents()
|
|||
if ( mutedDicts.size() )
|
||||
Utils::Url::addQueryItem( currentUrl, "muted", mutedDicts );
|
||||
|
||||
saveHistoryUserData();
|
||||
|
||||
ui.definition->load( currentUrl );
|
||||
load( currentUrl );
|
||||
|
||||
//QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
ui.definition->setCursor( Qt::WaitCursor );
|
||||
|
@ -1609,6 +1592,11 @@ void ArticleView::setSelectionBySingleClick( bool set )
|
|||
ui.definition->setSelectionBySingleClick( set );
|
||||
}
|
||||
|
||||
void ArticleView::setDelayedHighlightText(QString const & text)
|
||||
{
|
||||
delayedHighlightText = text;
|
||||
}
|
||||
|
||||
void ArticleView::back()
|
||||
{
|
||||
// Don't allow navigating back to page 0, which is usually the initial
|
||||
|
@ -1626,9 +1614,14 @@ void ArticleView::forward()
|
|||
ui.definition->forward();
|
||||
}
|
||||
|
||||
void ArticleView::reload()
|
||||
{
|
||||
ui.definition->reload();
|
||||
}
|
||||
|
||||
void ArticleView::hasSound( const std::function< void( bool ) > & callback )
|
||||
{
|
||||
ui.definition->page()->runJavaScript( "gdAudioLinks.first",
|
||||
ui.definition->page()->runJavaScript( "if(typeof(gdAudioLinks)!=\"undefined\") gdAudioLinks.first",
|
||||
[ callback ]( const QVariant & v )
|
||||
{
|
||||
bool has = false;
|
||||
|
@ -1713,14 +1706,13 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
{
|
||||
// Is that a link? Is there a selection?
|
||||
QWebEnginePage* r=ui.definition->page();
|
||||
updateCurrentArticleFromCurrentFrame(ui.definition->page(), const_cast<QPoint *>(& pos));
|
||||
|
||||
QMenu menu( this );
|
||||
|
||||
QAction * followLink = 0;
|
||||
QAction * followLinkExternal = 0;
|
||||
QAction * followLinkNewTab = 0;
|
||||
QAction * lookupSelection = 0;
|
||||
QAction * sendToAnkiAction = 0 ;
|
||||
QAction * lookupSelectionGr = 0;
|
||||
QAction * lookupSelectionNewTab = 0;
|
||||
QAction * lookupSelectionNewTabGr = 0;
|
||||
|
@ -1730,6 +1722,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
QAction * sendWordToInputLineAction = 0;
|
||||
QAction * saveImageAction = 0;
|
||||
QAction * saveSoundAction = 0;
|
||||
QAction * saveBookmark = 0;
|
||||
|
||||
#if( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
|
||||
const QWebEngineContextMenuData * menuData = &(r->contextMenuData());
|
||||
|
@ -1788,7 +1781,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
}
|
||||
|
||||
QString selectedText = ui.definition->selectedText();
|
||||
QString text = selectedText.trimmed();
|
||||
QString text = Utils::trimNonChar( selectedText );
|
||||
|
||||
if ( text.size() && text.size() < 60 )
|
||||
{
|
||||
|
@ -1850,6 +1843,21 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
}
|
||||
}
|
||||
|
||||
if(text.size())
|
||||
{
|
||||
// avoid too long in the menu ,use left 30 characters.
|
||||
saveBookmark = new QAction( tr( "Save &Bookmark \"%1...\"" ).arg( text.left( 30 ) ), &menu );
|
||||
menu.addAction( saveBookmark );
|
||||
}
|
||||
|
||||
// add anki menu
|
||||
if( !text.isEmpty() && cfg.preferences.ankiConnectServer.enabled )
|
||||
{
|
||||
QString txt = ui.definition->title();
|
||||
sendToAnkiAction = new QAction( tr( "&Send \"%1\" to anki with selected text." ).arg( txt ), &menu );
|
||||
menu.addAction( sendToAnkiAction );
|
||||
}
|
||||
|
||||
if( text.isEmpty() && !cfg.preferences.storeHistory)
|
||||
{
|
||||
QString txt = ui.definition->title();
|
||||
|
@ -1941,7 +1949,15 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
QDesktopServices::openUrl( targetUrl );
|
||||
else
|
||||
if ( result == lookupSelection )
|
||||
showDefinition( selectedText, getGroup( ui.definition->url() ), getCurrentArticle() );
|
||||
showDefinition( text, getGroup( ui.definition->url() ), getCurrentArticle() );
|
||||
else if( result == saveBookmark )
|
||||
{
|
||||
emit saveBookmarkSignal( text.left( 60 ) );
|
||||
}
|
||||
else if( result == sendToAnkiAction )
|
||||
{
|
||||
sendToAnki( ui.definition->title(), ui.definition->selectedText() );
|
||||
}
|
||||
else
|
||||
if ( result == lookupSelectionGr && groupComboBox )
|
||||
showDefinition( selectedText, groupComboBox->getCurrentGroup(), QString() );
|
||||
|
@ -2339,42 +2355,44 @@ void ArticleView::performFindOperation( bool restart, bool backwards, bool check
|
|||
if ( backwards )
|
||||
f |= QWebEnginePage::FindBackward;
|
||||
|
||||
bool setMark = text.size() && !findText(text, f);
|
||||
findText( text,
|
||||
f,
|
||||
[ &text, this ]( bool match )
|
||||
{
|
||||
bool setMark = !text.isEmpty() && !match;
|
||||
|
||||
if ( ui.searchText->property( "noResults" ).toBool() != setMark )
|
||||
{
|
||||
ui.searchText->setProperty( "noResults", setMark );
|
||||
if( ui.searchText->property( "noResults" ).toBool() != setMark )
|
||||
{
|
||||
ui.searchText->setProperty( "noResults", setMark );
|
||||
|
||||
// Reload stylesheet
|
||||
reloadStyleSheet();
|
||||
}
|
||||
// Reload stylesheet
|
||||
reloadStyleSheet();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
bool ArticleView::findText(QString& text, const QWebEnginePage::FindFlags& f)
|
||||
void ArticleView::findText( QString & text,
|
||||
const QWebEnginePage::FindFlags & f,
|
||||
const std::function< void( bool match ) > & callback )
|
||||
{
|
||||
bool r;
|
||||
// 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( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
|
||||
ui.definition->findText( text,
|
||||
f,
|
||||
[ callback ]( const QWebEngineFindTextResult & result )
|
||||
{
|
||||
if(loop->isRunning()){
|
||||
r = result.numberOfMatches()>0;
|
||||
loop->quit();
|
||||
} });
|
||||
auto r = result.numberOfMatches() > 0;
|
||||
if( callback )
|
||||
callback( r );
|
||||
} );
|
||||
#else
|
||||
ui.definition->findText(text, f, [&](bool result)
|
||||
ui.definition->findText( text,
|
||||
f,
|
||||
[ callback ]( bool result )
|
||||
{
|
||||
if(loop->isRunning()){
|
||||
r = result;
|
||||
loop->quit();
|
||||
} });
|
||||
if( callback )
|
||||
callback( result );
|
||||
} );
|
||||
#endif
|
||||
|
||||
|
||||
loop->exec();
|
||||
return r;
|
||||
}
|
||||
|
||||
void ArticleView::reloadStyleSheet()
|
||||
|
@ -2440,25 +2458,12 @@ void ArticleView::showEvent( QShowEvent * ev )
|
|||
void ArticleView::receiveExpandOptionalParts( bool expand )
|
||||
{
|
||||
if( expandOptionalParts != expand )
|
||||
{
|
||||
int n = getArticlesList().indexOf( getActiveArticleId() );
|
||||
if( n > 0 )
|
||||
articleToJump = getCurrentArticle();
|
||||
|
||||
emit setExpandMode( expand );
|
||||
expandOptionalParts = expand;
|
||||
reload();
|
||||
}
|
||||
switchExpandOptionalParts();
|
||||
}
|
||||
|
||||
void ArticleView::switchExpandOptionalParts()
|
||||
{
|
||||
expandOptionalParts = !expandOptionalParts;
|
||||
|
||||
int n = getArticlesList().indexOf( getActiveArticleId() );
|
||||
if( n > 0 )
|
||||
articleToJump = getCurrentArticle();
|
||||
|
||||
emit setExpandMode( expandOptionalParts );
|
||||
reload();
|
||||
}
|
||||
|
@ -2498,6 +2503,12 @@ void ArticleView::highlightFTSResults()
|
|||
else
|
||||
regString = regString.remove( AccentMarkHandler::accentMark() );
|
||||
|
||||
//<div><i>watch</i>out</div> to plainText will return "watchout".
|
||||
//if application goes here,that means the article text must contains the search text.
|
||||
//whole word match regString will contain \b . can not match the above senario.
|
||||
//workaround ,remove \b from the regstring="(\bwatch\b)"
|
||||
regString.remove( QRegularExpression( "\\\\b" ) );
|
||||
|
||||
QRegularExpression regexp;
|
||||
if( Utils::Url::hasQueryItem( url, "wildcards" ) )
|
||||
regexp.setPattern( wildcardsToRegexp( regString ) );
|
||||
|
@ -2548,17 +2559,15 @@ void ArticleView::highlightFTSResults()
|
|||
if( ftsSearchMatchCase )
|
||||
flags |= QWebEnginePage::FindCaseSensitively;
|
||||
|
||||
for( int x = 0; x < allMatches.size(); x++ )
|
||||
ui.definition->findText( allMatches.at( x ), flags );
|
||||
|
||||
if( !allMatches.isEmpty() )
|
||||
{
|
||||
// highlightAllFtsOccurences( flags );
|
||||
ui.definition->findText( allMatches.at( 0 ), flags );
|
||||
// if( ui.definition->findText( allMatches.at( 0 ), flags ) )
|
||||
{
|
||||
ui.definition->page()->runJavaScript(
|
||||
QString( "%1=window.getSelection().getRangeAt(0);_=0;" ).arg( rangeVarName ) );
|
||||
}
|
||||
// {
|
||||
// ui.definition->page()->runJavaScript(
|
||||
// QString( "%1=window.getSelection().getRangeAt(0);_=0;" ).arg( rangeVarName ) );
|
||||
// }
|
||||
}
|
||||
|
||||
ui.ftsSearchFrame->show();
|
||||
|
@ -2569,6 +2578,25 @@ void ArticleView::highlightFTSResults()
|
|||
} );
|
||||
}
|
||||
|
||||
void ArticleView::highlightAllFtsOccurences( QWebEnginePage::FindFlags flags )
|
||||
{
|
||||
// Usually allMatches contains mostly duplicates. Thus searching for each element of
|
||||
// allMatches to highlight them takes a long time => collect unique elements into a
|
||||
// set and search for them instead.
|
||||
// Don't use QList::toSet() or QSet's range constructor because they reserve space
|
||||
// for QList::size() elements, whereas the final QSet size is likely 1 or 2.
|
||||
QSet< QString > uniqueMatches;
|
||||
for( int x = 0; x < allMatches.size(); ++x )
|
||||
{
|
||||
QString const & match = allMatches.at( x );
|
||||
// Consider words that differ only in case equal if the search is case-insensitive.
|
||||
uniqueMatches.insert( ftsSearchMatchCase ? match : match.toLower() );
|
||||
}
|
||||
|
||||
for( QSet< QString >::const_iterator it = uniqueMatches.constBegin(); it != uniqueMatches.constEnd(); ++it )
|
||||
ui.definition->findText( *it, flags );
|
||||
}
|
||||
|
||||
void ArticleView::setActiveDictIds(ActiveDictIds ad) {
|
||||
// ignore all other signals.
|
||||
qDebug() << "receive dicts, current word:" << currentWord << ad.word << ":" << ad.dictIds;
|
||||
|
@ -2651,9 +2679,9 @@ void ArticleView::performFtsFindOperation( bool backwards )
|
|||
}
|
||||
#endif
|
||||
// Store new highlighted selection
|
||||
ui.definition->page()->
|
||||
runJavaScript( QString( "%1=window.getSelection().getRangeAt(0);_=0;" )
|
||||
.arg( rangeVarName ) );
|
||||
// ui.definition->page()->
|
||||
// runJavaScript( QString( "%1=window.getSelection().getRangeAt(0);_=0;" )
|
||||
// .arg( rangeVarName ) );
|
||||
}
|
||||
|
||||
void ArticleView::on_ftsSearchPrevious_clicked()
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||
#include <QtCore5Compat/QRegExp>
|
||||
#endif
|
||||
#include "ankiconnector.h"
|
||||
|
||||
class ResourceToSaveHandler;
|
||||
class ArticleViewAgent ;
|
||||
|
@ -39,13 +40,14 @@ class ArticleView: public QFrame
|
|||
ArticleViewAgent * agent;
|
||||
Ui::ArticleView ui;
|
||||
|
||||
AnkiConnector * ankiConnector;
|
||||
|
||||
QAction pasteAction, articleUpAction, articleDownAction,
|
||||
goBackAction, goForwardAction, selectCurrentArticleAction,
|
||||
copyAsTextAction, inspectAction;
|
||||
QAction & openSearchAction;
|
||||
bool searchIsOpened;
|
||||
bool expandOptionalParts;
|
||||
QString articleToJump;
|
||||
QString rangeVarName;
|
||||
|
||||
/// Any resource we've decided to download off the dictionary gets stored here.
|
||||
|
@ -76,9 +78,11 @@ class ArticleView: public QFrame
|
|||
bool ftsSearchIsOpened, ftsSearchMatchCase;
|
||||
int ftsPosition;
|
||||
|
||||
QString delayedHighlightText;
|
||||
|
||||
void highlightFTSResults();
|
||||
void highlightAllFtsOccurences( QWebEnginePage::FindFlags flags );
|
||||
void performFtsFindOperation( bool backwards );
|
||||
void showFindButtons();
|
||||
|
||||
public:
|
||||
/// The popupView flag influences contents of the context menus to be
|
||||
|
@ -129,6 +133,7 @@ public:
|
|||
QRegExp const & searchRegExp, unsigned group,
|
||||
bool ignoreDiacritics );
|
||||
|
||||
void sendToAnki(QString const & word, QString const & text );
|
||||
/// Clears the view and sets the application-global waiting cursor,
|
||||
/// which will be restored when some article loads eventually.
|
||||
void showAnticipation();
|
||||
|
@ -153,6 +158,8 @@ public:
|
|||
/// Called when preference changes
|
||||
void setSelectionBySingleClick( bool set );
|
||||
|
||||
void setDelayedHighlightText(QString const & text);
|
||||
|
||||
public slots:
|
||||
|
||||
/// Goes back in history
|
||||
|
@ -168,8 +175,7 @@ public slots:
|
|||
public:
|
||||
|
||||
/// Reloads the view
|
||||
void reload()
|
||||
{ ui.definition->reload(); }
|
||||
void reload();
|
||||
|
||||
/// Returns true if there's an audio reference on the page, false otherwise.
|
||||
void hasSound( const std::function< void( bool has ) > & callback );
|
||||
|
@ -223,6 +229,10 @@ public:
|
|||
ResourceToSaveHandler * saveResource( const QUrl & url, const QString & fileName );
|
||||
ResourceToSaveHandler * saveResource( const QUrl & url, const QUrl & ref, const QString & fileName );
|
||||
|
||||
void findText( QString & text,
|
||||
const QWebEnginePage::FindFlags & f,
|
||||
const std::function< void( bool match ) > & callback = nullptr );
|
||||
|
||||
signals:
|
||||
|
||||
void iconChanged( ArticleView *, QIcon const & icon );
|
||||
|
@ -281,6 +291,8 @@ signals:
|
|||
|
||||
void inspectSignal(QWebEngineView * view);
|
||||
|
||||
void saveBookmarkSignal( const QString & bookmark );
|
||||
|
||||
public slots:
|
||||
|
||||
void on_searchPrevious_clicked();
|
||||
|
@ -360,7 +372,8 @@ private:
|
|||
|
||||
/// Sets the current article by executing a javascript code.
|
||||
/// If moveToIt is true, it moves the focus to it as well.
|
||||
void setCurrentArticle( QString const &, bool moveToIt = false );
|
||||
/// Returns true in case of success, false otherwise.
|
||||
bool setCurrentArticle( QString const &, bool moveToIt = false );
|
||||
|
||||
/// Checks if the given article in form of "gdfrom-xxx" is inside a "website"
|
||||
/// frame.
|
||||
|
@ -375,14 +388,13 @@ private:
|
|||
/// url to the appropriate "contexts" entry.
|
||||
void tryMangleWebsiteClickedUrl( QUrl & url, Contexts & contexts );
|
||||
|
||||
/// Use the known information about the current frame to update the current
|
||||
/// article's value.
|
||||
void updateCurrentArticleFromCurrentFrame( QWebEnginePage * frame = 0 ,QPoint * point=0);
|
||||
|
||||
/// Saves current article and scroll position for the current history item.
|
||||
/// Should be used when leaving the page.
|
||||
void saveHistoryUserData();
|
||||
|
||||
/// Loads a page at @p url into view.
|
||||
void load( QUrl const & url );
|
||||
|
||||
/// Attempts removing last temporary file created.
|
||||
void cleanupTemp();
|
||||
|
||||
|
@ -390,7 +402,6 @@ private:
|
|||
|
||||
void performFindOperation( bool restart, bool backwards, bool checkHighlight = false );
|
||||
|
||||
bool findText(QString& text, const QWebEnginePage::FindFlags& f);
|
||||
|
||||
void reloadStyleSheet();
|
||||
|
||||
|
|
|
@ -1,15 +1,38 @@
|
|||
#include "articlewebpage.h"
|
||||
#include "utils.hh"
|
||||
|
||||
ArticleWebPage::ArticleWebPage(QObject *parent)
|
||||
: QWebEnginePage{parent}
|
||||
{
|
||||
}
|
||||
bool ArticleWebPage::acceptNavigationRequest( const QUrl & url, NavigationType type, bool isMainFrame )
|
||||
bool ArticleWebPage::acceptNavigationRequest( const QUrl & resUrl, NavigationType type, bool isMainFrame )
|
||||
{
|
||||
QUrl url = resUrl;
|
||||
if( url.scheme() == "bword" || url.scheme() == "entry" )
|
||||
{
|
||||
url.setScheme( "gdlookup" );
|
||||
url.setHost( "localhost" );
|
||||
url.setPath( "" );
|
||||
auto [ valid, word ] = Utils::Url::getQueryWord( resUrl );
|
||||
Utils::Url::addQueryItem( url, "word", word );
|
||||
Utils::Url::addQueryItem( url, "group", lastReq.group );
|
||||
Utils::Url::addQueryItem( url, "muted", lastReq.mutedDicts );
|
||||
setUrl( url );
|
||||
return false;
|
||||
}
|
||||
|
||||
//save current gdlookup's values.
|
||||
if( url.scheme() == "gdlookup" )
|
||||
{
|
||||
lastReq.group = Utils::Url::queryItemValue( url, "group" );
|
||||
lastReq.mutedDicts = Utils::Url::queryItemValue( url, "muted" );
|
||||
}
|
||||
|
||||
if( type == QWebEnginePage::NavigationTypeLinkClicked )
|
||||
{
|
||||
emit linkClicked( url );
|
||||
return true;
|
||||
}
|
||||
|
||||
return QWebEnginePage::acceptNavigationRequest( url, type, isMainFrame );
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
#include <QWebEnginePage>
|
||||
|
||||
struct LastReqInfo{
|
||||
QString group;
|
||||
QString mutedDicts;
|
||||
};
|
||||
|
||||
class ArticleWebPage : public QWebEnginePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -12,6 +17,8 @@ signals:
|
|||
void linkClicked( const QUrl & url );
|
||||
protected:
|
||||
virtual bool acceptNavigationRequest( const QUrl & url, NavigationType type, bool isMainFrame );
|
||||
private:
|
||||
LastReqInfo lastReq;
|
||||
};
|
||||
|
||||
#endif // ARTICLEWEBPAGE_H
|
||||
|
|
58
base/globalregex.cc
Normal file
58
base/globalregex.cc
Normal file
|
@ -0,0 +1,58 @@
|
|||
#include "globalregex.hh"
|
||||
#include "fulltextsearch.hh"
|
||||
|
||||
using namespace RX;
|
||||
|
||||
QRegularExpression Ftx::regBrackets(
|
||||
"(\\([\\w\\p{M}]+\\)){0,1}([\\w\\p{M}]+)(\\([\\w\\p{M}]+\\)){0,1}([\\w\\p{M}]+){0,1}(\\([\\w\\p{M}]+\\)){0,1}",
|
||||
QRegularExpression::UseUnicodePropertiesOption );
|
||||
QRegularExpression Ftx::regSplit( "[^\\w\\p{M}]+", QRegularExpression::UseUnicodePropertiesOption );
|
||||
|
||||
QRegularExpression Ftx::spacesRegExp( "\\W+", QRegularExpression::UseUnicodePropertiesOption );
|
||||
QRegularExpression Ftx::wordRegExp( QString( "\\w{" ) + QString::number( FTS::MinimumWordSize ) + ",}",
|
||||
QRegularExpression::UseUnicodePropertiesOption );
|
||||
QRegularExpression Ftx::setsRegExp( "\\[[^\\]]+\\]", QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Ftx::regexRegExp( "\\\\[afnrtvdDwWsSbB]|\\\\x([0-9A-Fa-f]{4})|\\\\0([0-7]{3})",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
|
||||
QRegularExpression Ftx::handleRoundBracket( "[^\\w\\(\\)\\p{M}]+" ,
|
||||
QRegularExpression::UseUnicodePropertiesOption );
|
||||
QRegularExpression Ftx::noRoundBracket( "[^\\w\\p{M}]+",
|
||||
QRegularExpression::UseUnicodePropertiesOption );
|
||||
|
||||
|
||||
//mdx
|
||||
|
||||
QRegularExpression Mdx::allLinksRe( "(?:<\\s*(a(?:rea)?|img|link|script|source)(?:\\s+[^>]+|\\s*)>)",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::wordCrossLink( "([\\s\"']href\\s*=)\\s*([\"'])entry://([^>#]*?)((?:#[^>]*?)?)\\2",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::anchorIdRe( "([\\s\"'](?:name|id)\\s*=)\\s*([\"'])\\s*(?=\\S)",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::anchorIdReWord( "([\\s\"'](?:name|id)\\s*=)\\s*([\"'])\\s*(?=\\S)([^\"]*)",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::anchorIdRe2( "([\\s\"'](?:name|id)\\s*=)\\s*(?=[^\"'])([^\\s\">]+)",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::anchorLinkRe( "([\\s\"']href\\s*=\\s*[\"'])entry://#",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::audioRe( "([\\s\"']href\\s*=)\\s*([\"'])sound://([^\">]+)\\2",
|
||||
QRegularExpression::CaseInsensitiveOption
|
||||
| QRegularExpression::InvertedGreedinessOption );
|
||||
QRegularExpression Mdx::stylesRe( "([\\s\"']href\\s*=)\\s*([\"'])(?!\\s*\\b(?:(?:bres|https?|ftp)://"
|
||||
"|(?:data|javascript):))(?:file://)?[\\x00-\\x1f\\x7f]*\\.*/?([^\">]+)\\2",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::stylesRe2( "([\\s\"']href\\s*=)\\s*(?![\\s\"']|\\b(?:(?:bres|https?|ftp)://"
|
||||
"|(?:data|javascript):))(?:file://)?[\\x00-\\x1f\\x7f]*\\.*/?([^\\s\">]+)",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::inlineScriptRe( "<\\s*script(?:(?=\\s)(?:(?![\\s\"']src\\s*=)[^>])+|\\s*)>",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::closeScriptTagRe( "<\\s*/script\\s*>", QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::srcRe( "([\\s\"']src\\s*=)\\s*([\"'])(?!\\s*\\b(?:(?:bres|https?|ftp)://"
|
||||
"|(?:data|javascript):))(?:file://)?[\\x00-\\x1f\\x7f]*\\.*/?([^\">]+)\\2",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression Mdx::srcRe2( "([\\s\"']src\\s*=)\\s*(?![\\s\"']|\\b(?:(?:bres|https?|ftp)://"
|
||||
"|(?:data|javascript):))(?:file://)?[\\x00-\\x1f\\x7f]*\\.*/?([^\\s\">]+)",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
|
||||
QRegularExpression Mdx::links( "url\\(\\s*(['\"]?)([^'\"]*)(['\"]?)\\s*\\)",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
44
base/globalregex.hh
Normal file
44
base/globalregex.hh
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef GLOBALREGEX_HH
|
||||
#define GLOBALREGEX_HH
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace RX
|
||||
{
|
||||
class Ftx
|
||||
{
|
||||
public:
|
||||
static QRegularExpression regBrackets;
|
||||
static QRegularExpression regSplit;
|
||||
static QRegularExpression spacesRegExp;
|
||||
static QRegularExpression wordRegExp;
|
||||
static QRegularExpression setsRegExp;
|
||||
static QRegularExpression regexRegExp;
|
||||
static QRegularExpression handleRoundBracket;
|
||||
static QRegularExpression noRoundBracket;
|
||||
};
|
||||
|
||||
|
||||
class Mdx
|
||||
{
|
||||
public:
|
||||
static QRegularExpression allLinksRe;
|
||||
static QRegularExpression wordCrossLink;
|
||||
static QRegularExpression anchorIdRe;
|
||||
static QRegularExpression anchorIdReWord;
|
||||
static QRegularExpression anchorIdRe2;
|
||||
static QRegularExpression anchorLinkRe;
|
||||
static QRegularExpression audioRe;
|
||||
static QRegularExpression stylesRe;
|
||||
static QRegularExpression stylesRe2;
|
||||
static QRegularExpression inlineScriptRe;
|
||||
static QRegularExpression closeScriptTagRe;
|
||||
static QRegularExpression srcRe;
|
||||
static QRegularExpression srcRe2;
|
||||
|
||||
static QRegularExpression links;
|
||||
};
|
||||
|
||||
} // namespace RX
|
||||
|
||||
#endif // GLOBALREGEX_HH
|
12
bgl.cc
12
bgl.cc
|
@ -198,16 +198,16 @@ namespace
|
|||
BglDictionary( string const & id, string const & indexFile,
|
||||
string const & dictionaryFile );
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -249,7 +249,7 @@ namespace
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -302,7 +302,7 @@ namespace
|
|||
FTS_index_completed.ref();
|
||||
}
|
||||
|
||||
void BglDictionary::loadIcon() throw()
|
||||
void BglDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
|
@ -1399,15 +1399,18 @@ void BtreeIndex::getHeadwordsFromOffsets( QList<uint32_t> & offsets,
|
|||
for( unsigned i = 0; i < result.size(); i++ )
|
||||
{
|
||||
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() && *it == articleOffset )
|
||||
{
|
||||
if( isCancelled && Utils::AtomicInt::loadAcquire( *isCancelled ) )
|
||||
return;
|
||||
|
||||
headwords.append( QString::fromUtf8( ( result[ i ].prefix + result[ i ].word ).c_str() ) );
|
||||
auto word = QString::fromUtf8( ( result[ i ].prefix + result[ i ].word ).c_str() );
|
||||
|
||||
headwords.append( word );
|
||||
offsets.erase( it);
|
||||
begOffsets = offsets.begin();
|
||||
endOffsets = offsets.end();
|
||||
|
|
|
@ -155,7 +155,7 @@ public:
|
|||
BtreeDictionary( string const & id, vector< string > const & dictionaryFiles );
|
||||
|
||||
/// Btree-indexed dictionaries are usually a good source for compound searches.
|
||||
virtual Dictionary::Features getFeatures() const throw()
|
||||
virtual Dictionary::Features getFeatures() const noexcept
|
||||
{ return Dictionary::SuitableForCompoundSearching; }
|
||||
|
||||
/// This function does the search using the btree index. Derivatives usually
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
~CharacterConversionDictionary();
|
||||
|
||||
std::vector< gd::wstring > getAlternateWritings( gd::wstring const & )
|
||||
throw();
|
||||
noexcept;
|
||||
};
|
||||
|
||||
CharacterConversionDictionary::CharacterConversionDictionary( std::string const & id,
|
||||
|
@ -70,7 +70,7 @@ CharacterConversionDictionary::~CharacterConversionDictionary()
|
|||
}
|
||||
|
||||
std::vector< gd::wstring > CharacterConversionDictionary::getAlternateWritings( gd::wstring const & str )
|
||||
throw()
|
||||
noexcept
|
||||
{
|
||||
std::vector< gd::wstring > results;
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "chunkedstorage.hh"
|
||||
#include <zlib.h>
|
||||
#include <string.h>
|
||||
#include <QDataStream>
|
||||
#include <QScopeGuard>
|
||||
|
||||
namespace ChunkedStorage {
|
||||
|
||||
|
@ -134,25 +136,42 @@ char * Reader::getBlock( uint32_t address, vector< char > & chunk )
|
|||
|
||||
// Read and decompress the chunk
|
||||
{
|
||||
file.seek( offsets[ chunkIdx ] );
|
||||
// file.seek( offsets[ chunkIdx ] );
|
||||
QMutexLocker _( &file.lock );
|
||||
auto bytes = file.map( offsets[ chunkIdx ], 8 );
|
||||
if( bytes == nullptr )
|
||||
throw mapFailed();
|
||||
auto qBytes = QByteArray::fromRawData( reinterpret_cast< char * >(bytes), 8 );
|
||||
QDataStream in( qBytes );
|
||||
in.setByteOrder( QDataStream::LittleEndian );
|
||||
|
||||
uint32_t uncompressedSize = file.read< uint32_t >();
|
||||
uint32_t compressedSize = file.read< uint32_t >();
|
||||
uint32_t uncompressedSize;
|
||||
uint32_t compressedSize;
|
||||
|
||||
in >> uncompressedSize >> compressedSize;
|
||||
|
||||
file.unmap( bytes );
|
||||
chunk.resize( uncompressedSize );
|
||||
|
||||
vector< unsigned char > compressedData( compressedSize );
|
||||
|
||||
file.read( &compressedData.front(), compressedData.size() );
|
||||
// vector< unsigned char > compressedData( compressedSize );
|
||||
auto chunkDataBytes = file.map( offsets[ chunkIdx ] + 8, compressedSize );
|
||||
if( chunkDataBytes == nullptr )
|
||||
throw mapFailed();
|
||||
// file.read( &compressedData.front(), compressedData.size() );
|
||||
auto autoUnmap = qScopeGuard(
|
||||
[ & ] {
|
||||
file.unmap( chunkDataBytes );
|
||||
} );
|
||||
Q_UNUSED( autoUnmap )
|
||||
|
||||
unsigned long decompressedLength = chunk.size();
|
||||
|
||||
if ( uncompress( (unsigned char *)&chunk.front(),
|
||||
&decompressedLength,
|
||||
&compressedData.front(),
|
||||
compressedData.size() ) != Z_OK ||
|
||||
decompressedLength != chunk.size() )
|
||||
if( uncompress( (unsigned char *)&chunk.front(), &decompressedLength, chunkDataBytes, compressedSize ) != Z_OK
|
||||
|| decompressedLength != chunk.size() )
|
||||
{
|
||||
throw exFailedToDecompressChunk();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t offsetInChunk = address & 0xffFF;
|
||||
|
|
|
@ -25,6 +25,7 @@ DEF_EX( Ex, "Chunked storage exception", std::exception )
|
|||
DEF_EX( exFailedToCompressChunk, "Failed to compress a chunk", Ex )
|
||||
DEF_EX( exAddressOutOfRange, "The given chunked address is out of range", Ex )
|
||||
DEF_EX( exFailedToDecompressChunk, "Failed to decompress a chunk", Ex )
|
||||
DEF_EX( mapFailed, "Failed to map/unmap the file", Ex )
|
||||
|
||||
/// This class writes data blocks in chunks.
|
||||
class Writer
|
||||
|
|
61
config.cc
61
config.cc
|
@ -89,6 +89,10 @@ ProxyServer::ProxyServer(): enabled( false ), useSystemProxy( false ), type( Soc
|
|||
{
|
||||
}
|
||||
|
||||
AnkiConnectServer::AnkiConnectServer(): enabled( false ), host("127.0.0.1"), port( 8765 )
|
||||
{
|
||||
}
|
||||
|
||||
HotKey::HotKey(): modifiers( 0 ), key1( 0 ), key2( 0 )
|
||||
{
|
||||
}
|
||||
|
@ -937,6 +941,17 @@ Class load()
|
|||
c.preferences.proxyServer.systemProxyPassword = proxy.namedItem( "systemProxyPassword" ).toElement().text();
|
||||
}
|
||||
|
||||
QDomNode ankiConnectServer = preferences.namedItem( "ankiConnectServer" );
|
||||
|
||||
if ( !ankiConnectServer.isNull() )
|
||||
{
|
||||
c.preferences.ankiConnectServer.enabled = ( ankiConnectServer.toElement().attribute( "enabled" ) == "1" );
|
||||
c.preferences.ankiConnectServer.host = ankiConnectServer.namedItem( "host" ).toElement().text();
|
||||
c.preferences.ankiConnectServer.port = ankiConnectServer.namedItem( "port" ).toElement().text().toULong();
|
||||
c.preferences.ankiConnectServer.deck = ankiConnectServer.namedItem( "deck" ).toElement().text();
|
||||
c.preferences.ankiConnectServer.model = ankiConnectServer.namedItem( "model" ).toElement().text();
|
||||
}
|
||||
|
||||
if ( !preferences.namedItem( "checkForNewReleases" ).isNull() )
|
||||
c.preferences.checkForNewReleases = ( preferences.namedItem( "checkForNewReleases" ).toElement().text() == "1" );
|
||||
|
||||
|
@ -1872,6 +1887,32 @@ void save( Class const & c )
|
|||
proxy.appendChild( opt );
|
||||
}
|
||||
|
||||
//anki connect
|
||||
{
|
||||
QDomElement proxy = dd.createElement( "ankiConnectServer" );
|
||||
preferences.appendChild( proxy );
|
||||
|
||||
QDomAttr enabled = dd.createAttribute( "enabled" );
|
||||
enabled.setValue( c.preferences.ankiConnectServer.enabled ? "1" : "0" );
|
||||
proxy.setAttributeNode( enabled );
|
||||
|
||||
opt = dd.createElement( "host" );
|
||||
opt.appendChild( dd.createTextNode( c.preferences.ankiConnectServer.host ) );
|
||||
proxy.appendChild( opt );
|
||||
|
||||
opt = dd.createElement( "port" );
|
||||
opt.appendChild( dd.createTextNode( QString::number( c.preferences.ankiConnectServer.port ) ) );
|
||||
proxy.appendChild( opt );
|
||||
|
||||
opt = dd.createElement( "deck" );
|
||||
opt.appendChild( dd.createTextNode( c.preferences.ankiConnectServer.deck ) );
|
||||
proxy.appendChild( opt );
|
||||
|
||||
opt = dd.createElement( "model" );
|
||||
opt.appendChild( dd.createTextNode( c.preferences.ankiConnectServer.model ) );
|
||||
proxy.appendChild( opt );
|
||||
}
|
||||
|
||||
opt = dd.createElement( "checkForNewReleases" );
|
||||
opt.appendChild( dd.createTextNode( c.preferences.checkForNewReleases ? "1" : "0" ) );
|
||||
preferences.appendChild( opt );
|
||||
|
@ -2211,7 +2252,7 @@ QString getUserQtCssFileName()
|
|||
return getHomeDir().filePath( "qt-style.css" );
|
||||
}
|
||||
|
||||
QString getProgramDataDir() throw()
|
||||
QString getProgramDataDir() noexcept
|
||||
{
|
||||
if ( isPortableVersion() )
|
||||
return QCoreApplication::applicationDirPath();
|
||||
|
@ -2223,12 +2264,12 @@ QString getProgramDataDir() throw()
|
|||
#endif
|
||||
}
|
||||
|
||||
QString getEmbedLocDir() throw()
|
||||
QString getEmbedLocDir() noexcept
|
||||
{
|
||||
return ":/locale";
|
||||
}
|
||||
|
||||
QString getLocDir() throw()
|
||||
QString getLocDir() noexcept
|
||||
{
|
||||
if ( QDir( getProgramDataDir() ).cd( "locale" ) )
|
||||
return getProgramDataDir() + "/locale";
|
||||
|
@ -2236,7 +2277,7 @@ QString getLocDir() throw()
|
|||
return QCoreApplication::applicationDirPath() + "/locale";
|
||||
}
|
||||
|
||||
QString getHelpDir() throw()
|
||||
QString getHelpDir() noexcept
|
||||
{
|
||||
if ( QDir( getProgramDataDir() ).cd( "help" ) )
|
||||
return getProgramDataDir() + "/help";
|
||||
|
@ -2245,7 +2286,7 @@ QString getHelpDir() throw()
|
|||
}
|
||||
|
||||
#ifdef MAKE_CHINESE_CONVERSION_SUPPORT
|
||||
QString getOpenCCDir() throw()
|
||||
QString getOpenCCDir() noexcept
|
||||
{
|
||||
#if defined( Q_OS_WIN )
|
||||
if ( QDir( "opencc" ).exists() )
|
||||
|
@ -2264,7 +2305,7 @@ QString getOpenCCDir() throw()
|
|||
}
|
||||
#endif
|
||||
|
||||
bool isPortableVersion() throw()
|
||||
bool isPortableVersion() noexcept
|
||||
{
|
||||
struct IsPortable
|
||||
{
|
||||
|
@ -2279,7 +2320,7 @@ bool isPortableVersion() throw()
|
|||
return p.isPortable;
|
||||
}
|
||||
|
||||
QString getPortableVersionDictionaryDir() throw()
|
||||
QString getPortableVersionDictionaryDir() noexcept
|
||||
{
|
||||
if ( isPortableVersion() )
|
||||
return getProgramDataDir() + "/content";
|
||||
|
@ -2287,7 +2328,7 @@ QString getPortableVersionDictionaryDir() throw()
|
|||
return QString();
|
||||
}
|
||||
|
||||
QString getPortableVersionMorphoDir() throw()
|
||||
QString getPortableVersionMorphoDir() noexcept
|
||||
{
|
||||
if ( isPortableVersion() )
|
||||
return getPortableVersionDictionaryDir() + "/morphology";
|
||||
|
@ -2307,7 +2348,7 @@ QString getStylesDir()
|
|||
return result.path() + QDir::separator();
|
||||
}
|
||||
|
||||
QString getCacheDir() throw()
|
||||
QString getCacheDir() noexcept
|
||||
{
|
||||
return isPortableVersion() ? portableHomeDirPath() + "/cache"
|
||||
#ifdef HAVE_X11
|
||||
|
@ -2317,7 +2358,7 @@ QString getCacheDir() throw()
|
|||
#endif
|
||||
}
|
||||
|
||||
QString getNetworkCacheDir() throw()
|
||||
QString getNetworkCacheDir() noexcept
|
||||
{
|
||||
return getCacheDir() + "/network";
|
||||
}
|
||||
|
|
33
config.hh
33
config.hh
|
@ -137,6 +137,18 @@ struct ProxyServer
|
|||
ProxyServer();
|
||||
};
|
||||
|
||||
struct AnkiConnectServer
|
||||
{
|
||||
bool enabled;
|
||||
|
||||
QString host;
|
||||
unsigned port;
|
||||
QString deck;
|
||||
QString model;
|
||||
|
||||
AnkiConnectServer();
|
||||
};
|
||||
|
||||
// A hotkey -- currently qt modifiers plus one or two keys
|
||||
struct HotKey
|
||||
{
|
||||
|
@ -329,6 +341,7 @@ struct Preferences
|
|||
QString audioPlaybackProgram;
|
||||
|
||||
ProxyServer proxyServer;
|
||||
AnkiConnectServer ankiConnectServer;
|
||||
|
||||
bool checkForNewReleases;
|
||||
bool disallowContentFromOtherSites;
|
||||
|
@ -795,40 +808,40 @@ 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();
|
||||
QString getProgramDataDir() noexcept;
|
||||
|
||||
/// Returns the directory storing program localizized files (.qm).
|
||||
QString getEmbedLocDir() throw();
|
||||
QString getLocDir() throw();
|
||||
QString getEmbedLocDir() noexcept;
|
||||
QString getLocDir() noexcept;
|
||||
|
||||
/// Returns the directory storing program help files (.qch).
|
||||
QString getHelpDir() throw();
|
||||
QString getHelpDir() noexcept;
|
||||
|
||||
#ifdef MAKE_CHINESE_CONVERSION_SUPPORT
|
||||
/// Returns the directory storing OpenCC configuration and dictionary files (.json and .ocd).
|
||||
QString getOpenCCDir() throw();
|
||||
QString getOpenCCDir() noexcept;
|
||||
#endif
|
||||
|
||||
/// Returns true if the program is configured as a portable version. In that
|
||||
/// mode, all the settings and indices are kept in the program's directory.
|
||||
bool isPortableVersion() throw();
|
||||
bool isPortableVersion() noexcept;
|
||||
|
||||
/// Returns directory with dictionaries for portable version. It is content/
|
||||
/// in the application's directory.
|
||||
QString getPortableVersionDictionaryDir() throw();
|
||||
QString getPortableVersionDictionaryDir() noexcept;
|
||||
|
||||
/// Returns directory with morpgologies for portable version. It is
|
||||
/// content/morphology in the application's directory.
|
||||
QString getPortableVersionMorphoDir() throw();
|
||||
QString getPortableVersionMorphoDir() noexcept;
|
||||
|
||||
/// Returns the add-on styles directory.
|
||||
QString getStylesDir();
|
||||
|
||||
/// Returns the directory where user-specific non-essential (cached) data should be written.
|
||||
QString getCacheDir() throw();
|
||||
QString getCacheDir() noexcept;
|
||||
|
||||
/// Returns the article network disk cache directory.
|
||||
QString getNetworkCacheDir() throw();
|
||||
QString getNetworkCacheDir() noexcept;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -100,19 +100,19 @@ public:
|
|||
|
||||
~DictdDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
{ return idxHeader.langFrom; }
|
||||
|
@ -215,7 +215,7 @@ string nameFromFileName( string const & indexFileName )
|
|||
return Utf8::encode( FsEncoding::decode( string( sep + 1, dot - sep - 1 ) ) );
|
||||
}
|
||||
|
||||
void DictdDictionary::loadIcon() throw()
|
||||
void DictdDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
|
@ -159,7 +159,7 @@ sptr< WordSearchRequest > Class::findHeadwordsForSynonym( wstring const & )
|
|||
}
|
||||
|
||||
vector< wstring > Class::getAlternateWritings( wstring const & )
|
||||
throw()
|
||||
noexcept
|
||||
{
|
||||
return vector< wstring >();
|
||||
}
|
||||
|
@ -185,21 +185,21 @@ QString Class::getMainFilename()
|
|||
return QString();
|
||||
}
|
||||
|
||||
QIcon const & Class::getIcon() throw()
|
||||
QIcon const & Class::getIcon() noexcept
|
||||
{
|
||||
if( !dictionaryIconLoaded )
|
||||
loadIcon();
|
||||
return dictionaryIcon;
|
||||
}
|
||||
|
||||
QIcon const & Class::getNativeIcon() throw()
|
||||
QIcon const & Class::getNativeIcon() noexcept
|
||||
{
|
||||
if( !dictionaryIconLoaded )
|
||||
loadIcon();
|
||||
return dictionaryNativeIcon;
|
||||
}
|
||||
|
||||
void Class::loadIcon() throw()
|
||||
void Class::loadIcon() noexcept
|
||||
{
|
||||
dictionaryIconLoaded = true;
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ void Class::isolateCSS( QString & css, QString const & wrapperSelector )
|
|||
css = newCSS;
|
||||
}
|
||||
|
||||
string makeDictionaryId( vector< string > const & dictionaryFiles ) throw()
|
||||
string makeDictionaryId( vector< string > const & dictionaryFiles ) noexcept
|
||||
{
|
||||
std::vector< string > sortedList;
|
||||
|
||||
|
@ -470,7 +470,7 @@ string makeDictionaryId( vector< string > const & dictionaryFiles ) throw()
|
|||
// of a timestamp of the file, so we use here Qt anyway. It is supposed to
|
||||
// be fixed in the future when it's needed.
|
||||
bool needToRebuildIndex( vector< string > const & dictionaryFiles,
|
||||
string const & indexFile ) throw()
|
||||
string const & indexFile ) noexcept
|
||||
{
|
||||
unsigned long lastModified = 0;
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ protected:
|
|||
|
||||
// Load user icon if it exist
|
||||
// By default set icon to empty
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
// Load icon from filename directly if isFullName == true
|
||||
// else treat filename as name without extension
|
||||
|
@ -295,39 +295,39 @@ public:
|
|||
virtual void deferredInit();
|
||||
|
||||
/// Returns the dictionary's id.
|
||||
string getId() throw()
|
||||
string getId() noexcept
|
||||
{ return id; }
|
||||
|
||||
/// Returns the list of file names the dictionary consists of.
|
||||
vector< string > const & getDictionaryFilenames() throw()
|
||||
vector< string > const & getDictionaryFilenames() noexcept
|
||||
{ return dictionaryFiles; }
|
||||
|
||||
/// Returns the dictionary's full name, utf8.
|
||||
virtual string getName() throw()=0;
|
||||
virtual string getName() noexcept=0;
|
||||
|
||||
/// Returns all the available properties, like the author's name, copyright,
|
||||
/// description etc. All strings are in utf8.
|
||||
virtual map< Property, string > getProperties() throw()=0;
|
||||
virtual map< Property, string > getProperties() noexcept=0;
|
||||
|
||||
/// Returns the features the dictionary possess. See the Feature enum for
|
||||
/// their list.
|
||||
virtual Features getFeatures() const throw()
|
||||
virtual Features getFeatures() const noexcept
|
||||
{ return NoFeatures; }
|
||||
|
||||
/// Returns the number of articles in the dictionary.
|
||||
virtual unsigned long getArticleCount() throw()=0;
|
||||
virtual unsigned long getArticleCount() noexcept=0;
|
||||
|
||||
/// Returns the number of words in the dictionary. This can be equal to
|
||||
/// the number of articles, or can be larger if some synonyms are present.
|
||||
virtual unsigned long getWordCount() throw()=0;
|
||||
virtual unsigned long getWordCount() noexcept=0;
|
||||
|
||||
/// Returns the dictionary's icon.
|
||||
virtual QIcon const & getIcon() throw();
|
||||
virtual QIcon const & getIcon() noexcept;
|
||||
|
||||
/// Returns the dictionary's native icon. Dsl icons are usually rectangular,
|
||||
/// and are adapted by getIcon() to be square. This function allows getting
|
||||
/// the original icon with no geometry transformations applied.
|
||||
virtual QIcon const & getNativeIcon() throw();
|
||||
virtual QIcon const & getNativeIcon() noexcept;
|
||||
|
||||
/// Returns the dictionary's source language.
|
||||
virtual quint32 getLangFrom() const
|
||||
|
@ -371,7 +371,7 @@ public:
|
|||
/// supposed to be very fast and simple, and the results are thus returned
|
||||
/// synchronously.
|
||||
virtual vector< wstring > getAlternateWritings( wstring const & )
|
||||
throw();
|
||||
noexcept;
|
||||
|
||||
/// Returns a definition for the given word. The definition should
|
||||
/// be an html fragment (without html/head/body tags) in an utf8 encoding.
|
||||
|
@ -454,7 +454,7 @@ public:
|
|||
/// dictionary is being indexed. Since indexing can take some time, this
|
||||
/// is useful to show in some kind of a splash screen.
|
||||
/// The dictionaryName is in utf8.
|
||||
virtual void indexingDictionary( string const & dictionaryName ) throw()=0;
|
||||
virtual void indexingDictionary( string const & dictionaryName ) noexcept=0;
|
||||
|
||||
virtual ~Initializing()
|
||||
{}
|
||||
|
@ -465,7 +465,7 @@ public:
|
|||
/// hashing the file names. This id should be used to identify dictionary
|
||||
/// and for the index file name, if one is needed.
|
||||
/// This function is supposed to be used by dictionary implementations.
|
||||
string makeDictionaryId( vector< string > const & dictionaryFiles ) throw();
|
||||
string makeDictionaryId( vector< string > const & dictionaryFiles ) noexcept;
|
||||
|
||||
/// Checks if it is needed to regenerate index file based on its timestamp
|
||||
/// and the timestamps of the dictionary files. If some files are newer than
|
||||
|
@ -473,7 +473,7 @@ string makeDictionaryId( vector< string > const & dictionaryFiles ) throw();
|
|||
/// dictionary files don't exist, returns true, too.
|
||||
/// This function is supposed to be used by dictionary implementations.
|
||||
bool needToRebuildIndex( vector< string > const & dictionaryFiles,
|
||||
string const & indexFile ) throw();
|
||||
string const & indexFile ) noexcept;
|
||||
|
||||
/// Returns a random dictionary id useful for interactively created
|
||||
/// dictionaries.
|
||||
|
|
|
@ -209,16 +209,16 @@ public:
|
|||
strategies.append( "prefix" );
|
||||
}
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return name; }
|
||||
|
||||
virtual map< Property, string > getProperties() throw()
|
||||
virtual map< Property, string > getProperties() noexcept
|
||||
{ return map< Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual sptr< WordSearchRequest > prefixMatch( wstring const &,
|
||||
|
@ -237,7 +237,7 @@ public:
|
|||
virtual QString const & getDescription();
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
void getServerDatabases();
|
||||
|
||||
|
@ -245,7 +245,7 @@ protected:
|
|||
friend class DictServerArticleRequest;
|
||||
};
|
||||
|
||||
void DictServerDictionary::loadIcon() throw()
|
||||
void DictServerDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
97
dsl.cc
97
dsl.cc
|
@ -128,11 +128,7 @@ struct InsidedCard
|
|||
InsidedCard( uint32_t _offset, uint32_t _size, QVector< wstring > const & words ) :
|
||||
offset( _offset ), size( _size ), headwords( words )
|
||||
{}
|
||||
InsidedCard( InsidedCard const & e ) :
|
||||
offset( e.offset ), size( e.size ), headwords( e.headwords )
|
||||
{}
|
||||
InsidedCard() {}
|
||||
|
||||
};
|
||||
|
||||
bool indexIsOldOrBad( string const & indexFile, bool hasZipFile )
|
||||
|
@ -187,16 +183,16 @@ public:
|
|||
|
||||
~DslDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -251,7 +247,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -470,7 +466,7 @@ void DslDictionary::doDeferredInit()
|
|||
}
|
||||
|
||||
|
||||
void DslDictionary::loadIcon() throw()
|
||||
void DslDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
@ -1556,32 +1552,8 @@ void DslDictionary::getArticleText( uint32_t articleAddress, QString & headword,
|
|||
|
||||
/// DslDictionary::getArticle()
|
||||
|
||||
class DslArticleRequest;
|
||||
|
||||
class DslArticleRequestRunnable: public QRunnable
|
||||
{
|
||||
DslArticleRequest & r;
|
||||
QSemaphore & hasExited;
|
||||
|
||||
public:
|
||||
|
||||
DslArticleRequestRunnable( DslArticleRequest & r_,
|
||||
QSemaphore & hasExited_ ): r( r_ ),
|
||||
hasExited( hasExited_ )
|
||||
{}
|
||||
|
||||
~DslArticleRequestRunnable()
|
||||
{
|
||||
hasExited.release();
|
||||
}
|
||||
|
||||
virtual void run();
|
||||
};
|
||||
|
||||
class DslArticleRequest: public Dictionary::DataRequest
|
||||
{
|
||||
friend class DslArticleRequestRunnable;
|
||||
|
||||
wstring word;
|
||||
vector< wstring > alts;
|
||||
DslDictionary & dict;
|
||||
|
@ -1597,11 +1569,10 @@ public:
|
|||
DslDictionary & dict_, bool ignoreDiacritics_ ):
|
||||
word( word_ ), alts( alts_ ), dict( dict_ ), ignoreDiacritics( ignoreDiacritics_ )
|
||||
{
|
||||
QThreadPool::globalInstance()->start(
|
||||
new DslArticleRequestRunnable( *this, hasExited ) );
|
||||
QThreadPool::globalInstance()->start( [ this ]() { this->run(); } );
|
||||
}
|
||||
|
||||
void run(); // Run from another thread by DslArticleRequestRunnable
|
||||
void run();
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
|
@ -1611,15 +1582,10 @@ public:
|
|||
~DslArticleRequest()
|
||||
{
|
||||
isCancelled.ref();
|
||||
hasExited.acquire();
|
||||
//hasExited.acquire();
|
||||
}
|
||||
};
|
||||
|
||||
void DslArticleRequestRunnable::run()
|
||||
{
|
||||
r.run();
|
||||
}
|
||||
|
||||
void DslArticleRequest::run()
|
||||
{
|
||||
if ( Utils::AtomicInt::loadAcquire( isCancelled ) )
|
||||
|
@ -1731,7 +1697,7 @@ void DslArticleRequest::run()
|
|||
{
|
||||
gdWarning( "DSL: Failed loading article from \"%s\", reason: %s\n", dict.getName().c_str(), ex.what() );
|
||||
articleText = string( "<span class=\"dsl_article\">" )
|
||||
+ string( QObject::tr( "Article loading error" ).toUtf8().constData() )
|
||||
+ QObject::tr( "Article loading error" ).toStdString()
|
||||
+ "</span>";
|
||||
}
|
||||
|
||||
|
@ -1759,32 +1725,8 @@ sptr< Dictionary::DataRequest > DslDictionary::getArticle( wstring const & word,
|
|||
|
||||
//// DslDictionary::getResource()
|
||||
|
||||
class DslResourceRequest;
|
||||
|
||||
class DslResourceRequestRunnable: public QRunnable
|
||||
{
|
||||
DslResourceRequest & r;
|
||||
QSemaphore & hasExited;
|
||||
|
||||
public:
|
||||
|
||||
DslResourceRequestRunnable( DslResourceRequest & r_,
|
||||
QSemaphore & hasExited_ ): r( r_ ),
|
||||
hasExited( hasExited_ )
|
||||
{}
|
||||
|
||||
~DslResourceRequestRunnable()
|
||||
{
|
||||
hasExited.release();
|
||||
}
|
||||
|
||||
virtual void run();
|
||||
};
|
||||
|
||||
class DslResourceRequest: public Dictionary::DataRequest
|
||||
{
|
||||
friend class DslResourceRequestRunnable;
|
||||
|
||||
DslDictionary & dict;
|
||||
|
||||
string resourceName;
|
||||
|
@ -1799,11 +1741,10 @@ public:
|
|||
dict( dict_ ),
|
||||
resourceName( resourceName_ )
|
||||
{
|
||||
QThreadPool::globalInstance()->start(
|
||||
new DslResourceRequestRunnable( *this, hasExited ) );
|
||||
QThreadPool::globalInstance()->start( [ this ]() { this->run(); } );
|
||||
}
|
||||
|
||||
void run(); // Run from another thread by DslResourceRequestRunnable
|
||||
void run();
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
|
@ -1813,15 +1754,10 @@ public:
|
|||
~DslResourceRequest()
|
||||
{
|
||||
isCancelled.ref();
|
||||
hasExited.acquire();
|
||||
//hasExited.acquire();
|
||||
}
|
||||
};
|
||||
|
||||
void DslResourceRequestRunnable::run()
|
||||
{
|
||||
r.run();
|
||||
}
|
||||
|
||||
void DslResourceRequest::run()
|
||||
{
|
||||
// Some runnables linger enough that they are cancelled before they start
|
||||
|
@ -2153,10 +2089,9 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
|
||||
hasString = false;
|
||||
|
||||
// The line read should either consist of pure whitespace, or be a
|
||||
// headword
|
||||
|
||||
if ( curString.empty() )
|
||||
// The line read should either consist of pure whitespace, or be a headword
|
||||
// skip too long headword,it can never be headword.
|
||||
if( curString.empty() || curString.size() > 100 )
|
||||
continue;
|
||||
|
||||
if ( isDslWs( curString[ 0 ] ) )
|
||||
|
|
|
@ -983,7 +983,7 @@ DslScanner::DslScanner( string const & fileName ) :
|
|||
readBufferLeft = 0;
|
||||
}
|
||||
|
||||
DslScanner::~DslScanner() throw()
|
||||
DslScanner::~DslScanner() noexcept
|
||||
{
|
||||
gzclose( f );
|
||||
}
|
||||
|
@ -1155,12 +1155,6 @@ 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 ];
|
||||
|
|
|
@ -113,7 +113,6 @@ class DslScanner
|
|||
wstring langFrom, langTo;
|
||||
wstring soundDictionary;
|
||||
char readBuffer[ 65536 ];
|
||||
QTextStream* fragStream;
|
||||
char * readBufferPtr;
|
||||
LineFeed lineFeed;
|
||||
size_t readBufferLeft;
|
||||
|
@ -130,7 +129,7 @@ public:
|
|||
DEF_EX( exEncodingError, "Encoding error", Ex ) // Should never happen really
|
||||
|
||||
DslScanner( string const & fileName ) ;
|
||||
~DslScanner() throw();
|
||||
~DslScanner() noexcept;
|
||||
|
||||
/// Returns the detected encoding of this file.
|
||||
Encoding getEncoding() const
|
||||
|
|
14
epwing.cc
14
epwing.cc
|
@ -44,7 +44,7 @@ namespace {
|
|||
enum
|
||||
{
|
||||
Signature = 0x58575045, // EPWX on little-endian, XWPE on big-endian
|
||||
CurrentFormatVersion = 5 + BtreeIndexing::FormatVersion + Folding::Version
|
||||
CurrentFormatVersion = 6 + BtreeIndexing::FormatVersion + Folding::Version
|
||||
};
|
||||
|
||||
struct IdxHeader
|
||||
|
@ -96,16 +96,16 @@ public:
|
|||
|
||||
~EpwingDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return bookName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -163,7 +163,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
void loadIcon() throw();
|
||||
void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -244,7 +244,7 @@ EpwingDictionary::~EpwingDictionary()
|
|||
removeDirectory( cacheDirectory );
|
||||
}
|
||||
|
||||
void EpwingDictionary::loadIcon() throw()
|
||||
void EpwingDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
|
@ -850,14 +850,14 @@ void EpwingBook::getFirstHeadword( EpwingHeadword & head )
|
|||
fixHeadword( head.headword );
|
||||
|
||||
EWPos epos( pos.page, pos.offset );
|
||||
allHeadwordPositions[ head.headword ] = epos;
|
||||
allHeadwordPositions[ head.headword ] << epos;
|
||||
}
|
||||
|
||||
bool EpwingBook::getNextHeadword( EpwingHeadword & head )
|
||||
{
|
||||
EB_Position pos;
|
||||
|
||||
QRegularExpression badLinks( "#(v|n)\\d" );
|
||||
QRegularExpression badLinks( "#(v|n)\\d", QRegularExpression::UseUnicodePropertiesOption);
|
||||
|
||||
// At first we check references queue
|
||||
while( !LinksQueue.isEmpty() )
|
||||
|
@ -881,13 +881,25 @@ bool EpwingBook::getNextHeadword( EpwingHeadword & head )
|
|||
|
||||
if( allHeadwordPositions.contains( head.headword ) )
|
||||
{
|
||||
EWPos epos = allHeadwordPositions[ head.headword ];
|
||||
if( pos.page != epos.first || abs( pos.offset - epos.second ) > 4 )
|
||||
// existed position
|
||||
bool existed = false;
|
||||
foreach( EWPos epos, allHeadwordPositions[ head.headword ] )
|
||||
{
|
||||
if( pos.page == epos.first && abs( pos.offset - epos.second ) <= 4 )
|
||||
{
|
||||
existed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !existed )
|
||||
{
|
||||
allHeadwordPositions[ head.headword ] << EWPos( pos.page, pos.offset );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
allHeadwordPositions[ head.headword ] = EWPos( pos.page, pos.offset );
|
||||
allHeadwordPositions[ head.headword ] << EWPos( pos.page, pos.offset );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -943,14 +955,26 @@ bool EpwingBook::getNextHeadword( EpwingHeadword & head )
|
|||
|
||||
if( allHeadwordPositions.contains( head.headword ) )
|
||||
{
|
||||
EWPos epos = allHeadwordPositions[ head.headword ];
|
||||
if( pos.page != epos.first || abs( pos.offset - epos.second ) > 4 )
|
||||
break;
|
||||
// existed position
|
||||
bool existed = false;
|
||||
foreach( EWPos epos, allHeadwordPositions[ head.headword ] )
|
||||
{
|
||||
if( pos.page == epos.first && abs( pos.offset - epos.second ) <= 4 )
|
||||
{
|
||||
existed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !existed )
|
||||
{
|
||||
allHeadwordPositions[ head.headword ] << EWPos( pos.page, pos.offset );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
allHeadwordPositions[ head.headword ] = EWPos( pos.page, pos.offset );
|
||||
break;
|
||||
allHeadwordPositions[ head.headword ] << EWPos( pos.page, pos.offset );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1104,6 +1128,9 @@ void EpwingBook::getArticle( QString & headword, QString & articleText,
|
|||
headword = QString::fromUtf8( buffer, length );
|
||||
finalizeText( headword );
|
||||
|
||||
if( text_only )
|
||||
fixHeadword( headword );
|
||||
|
||||
articleText = getText( pos.page, pos.offset, text_only );
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ class EpwingBook
|
|||
QStringList imageCacheList, soundsCacheList, moviesCacheList, fontsCacheList;
|
||||
QMap< QString, QString > baseFontsMap, customFontsMap;
|
||||
QVector< int > refPages, refOffsets;
|
||||
QMap< QString, EWPos > allHeadwordPositions;
|
||||
QMap< QString, QList< EWPos > > allHeadwordPositions;
|
||||
QVector< EWPos > LinksQueue;
|
||||
int refOpenCount, refCloseCount;
|
||||
static Mutex libMutex;
|
||||
|
|
8
ex.hh
8
ex.hh
|
@ -14,8 +14,8 @@
|
|||
#define DEF_EX( exName, exDescription, exParent ) \
|
||||
class exName: public exParent { \
|
||||
public: \
|
||||
virtual const char * what() const throw() { return (exDescription); } \
|
||||
virtual ~exName() throw() {} };
|
||||
virtual const char * what() const noexcept { return (exDescription); } \
|
||||
virtual ~exName() noexcept {} };
|
||||
|
||||
/// Same as DEF_EX, but takes a runtime string argument, which gets concatenated
|
||||
/// with the description.
|
||||
|
@ -31,7 +31,7 @@ class exName: public exParent { \
|
|||
std::string value; \
|
||||
public: \
|
||||
exName( std::string const & value_ ): value( std::string( exDescription ) + " " + value_ ) {} \
|
||||
virtual const char * what() const throw() { return value.c_str(); } \
|
||||
virtual ~exName() throw() {} };
|
||||
virtual const char * what() const noexcept { return value.c_str(); } \
|
||||
virtual ~exName() noexcept {} };
|
||||
|
||||
#endif
|
||||
|
|
18
file.cc
18
file.cc
|
@ -65,7 +65,7 @@ void loadFromFile( std::string const & n, std::vector< char > & data )
|
|||
f.read( &data.front(), data.size() );
|
||||
}
|
||||
|
||||
bool exists( char const * filename ) throw()
|
||||
bool exists( char const * filename ) noexcept
|
||||
{
|
||||
#ifdef __WIN32
|
||||
#if defined(__WIN64) || defined(_MSC_VER)
|
||||
|
@ -256,6 +256,20 @@ void Class::seek( qint64 offset )
|
|||
throw exSeekError();
|
||||
}
|
||||
|
||||
uchar * Class::map( qint64 offset, qint64 size )
|
||||
{
|
||||
if( writeBuffer )
|
||||
flushWriteBuffer();
|
||||
|
||||
return f.map( offset, size );
|
||||
}
|
||||
|
||||
bool Class::unmap( uchar * address )
|
||||
{
|
||||
return f.unmap( address );
|
||||
}
|
||||
|
||||
|
||||
void Class::seekCur( qint64 offset )
|
||||
{
|
||||
if ( writeBuffer )
|
||||
|
@ -313,7 +327,7 @@ void Class::close()
|
|||
f.close();
|
||||
}
|
||||
|
||||
Class::~Class() throw()
|
||||
Class::~Class() noexcept
|
||||
{
|
||||
if ( f.isOpen() )
|
||||
{
|
||||
|
|
10
file.hh
10
file.hh
|
@ -9,6 +9,7 @@
|
|||
#include <vector>
|
||||
#include <QFile>
|
||||
#include "ex.hh"
|
||||
#include "mutex.hh"
|
||||
|
||||
/// A simple wrapper over FILE * operations with added write-buffering,
|
||||
/// used for non-Qt parts of code.
|
||||
|
@ -30,9 +31,9 @@ bool tryPossibleZipName( std::string const & name, std::string & copyTo );
|
|||
|
||||
void loadFromFile( std::string const & n, std::vector< char > & data );
|
||||
|
||||
bool exists( char const * filename ) throw();
|
||||
bool exists( char const * filename ) noexcept;
|
||||
|
||||
inline bool exists( std::string const & filename ) throw()
|
||||
inline bool exists( std::string const & filename ) noexcept
|
||||
{ return exists( filename.c_str() ); }
|
||||
|
||||
class Class
|
||||
|
@ -44,6 +45,7 @@ class Class
|
|||
void open( char const * filename, char const * mode ) ;
|
||||
|
||||
public:
|
||||
QMutex lock;
|
||||
|
||||
Class( char const * filename, char const * mode ) ;
|
||||
|
||||
|
@ -95,6 +97,7 @@ public:
|
|||
|
||||
/// Seeks in the file, relative to its beginning.
|
||||
void seek( qint64 offset ) ;
|
||||
uchar * map( qint64 offset, qint64 size );
|
||||
/// Seeks in the file, relative to the current position.
|
||||
void seekCur( qint64 offset ) ;
|
||||
/// Seeks in the file, relative to the end of file.
|
||||
|
@ -116,7 +119,8 @@ public:
|
|||
/// Closes the file. No further operations are valid.
|
||||
void close() ;
|
||||
|
||||
~Class() throw();
|
||||
~Class() noexcept;
|
||||
bool unmap( uchar * address );
|
||||
|
||||
private:
|
||||
|
||||
|
|
12
forvo.cc
12
forvo.cc
|
@ -42,16 +42,16 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return name; }
|
||||
|
||||
virtual map< Property, string > getProperties() throw()
|
||||
virtual map< Property, string > getProperties() noexcept
|
||||
{ return map< Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual sptr< WordSearchRequest > prefixMatch( wstring const & /*word*/,
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
};
|
||||
|
||||
|
@ -90,7 +90,7 @@ sptr< DataRequest > ForvoDictionary::getArticle( wstring const & word,
|
|||
netMgr );
|
||||
}
|
||||
|
||||
void ForvoDictionary::loadIcon() throw()
|
||||
void ForvoDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
807
ftshelpers.cc
807
ftshelpers.cc
File diff suppressed because it is too large
Load diff
|
@ -55,7 +55,8 @@ bool parseSearchString( QString const & str, QStringList & IndexWords,
|
|||
QRegExp & searchRegExp, int searchMode,
|
||||
bool matchCase,
|
||||
int distanceBetweenWords,
|
||||
bool & hasCJK );
|
||||
bool & hasCJK,
|
||||
bool ignoreWordsOrder = false );
|
||||
|
||||
void parseArticleForFts( uint32_t articleAddress, QString & articleText,
|
||||
QMap< QString, QVector< uint32_t > > & words,
|
||||
|
@ -65,28 +66,6 @@ void makeFTSIndex( BtreeIndexing::BtreeDictionary * dict, QAtomicInt & isCancell
|
|||
|
||||
bool isCJKChar( ushort ch );
|
||||
|
||||
class FTSResultsRequest;
|
||||
|
||||
class FTSResultsRequestRunnable : public QRunnable
|
||||
{
|
||||
FTSResultsRequest & r;
|
||||
QSemaphore & hasExited;
|
||||
|
||||
public:
|
||||
|
||||
FTSResultsRequestRunnable( FTSResultsRequest & r_,
|
||||
QSemaphore & hasExited_ ) : r( r_ ),
|
||||
hasExited( hasExited_ )
|
||||
{}
|
||||
|
||||
~FTSResultsRequestRunnable()
|
||||
{
|
||||
hasExited.release();
|
||||
}
|
||||
|
||||
virtual void run();
|
||||
};
|
||||
|
||||
class FTSResultsRequest : public Dictionary::DataRequest
|
||||
{
|
||||
BtreeIndexing::BtreeDictionary & dict;
|
||||
|
@ -102,18 +81,24 @@ class FTSResultsRequest : public Dictionary::DataRequest
|
|||
int wordsInIndex;
|
||||
|
||||
QAtomicInt isCancelled;
|
||||
QSemaphore hasExited;
|
||||
|
||||
QAtomicInt results;
|
||||
|
||||
QList< FTS::FtsHeadword > * foundHeadwords;
|
||||
|
||||
void checkArticles( QVector< uint32_t > const & offsets,
|
||||
QStringList const & words,
|
||||
QRegExp const & searchRegexp = QRegExp() );
|
||||
QRegularExpression createMatchRegex( QRegExp const & searchRegexp );
|
||||
|
||||
void checkSingleArticle( uint32_t offset,
|
||||
QStringList const & words,
|
||||
QRegularExpression const & searchRegexp = QRegularExpression() );
|
||||
|
||||
void indexSearch( BtreeIndexing::BtreeIndex & ftsIndex,
|
||||
sptr< ChunkedStorage::Reader > chunks,
|
||||
QStringList & indexWords,
|
||||
QStringList & searchWords );
|
||||
QStringList & searchWords, QRegExp & regexp );
|
||||
|
||||
void combinedIndexSearch( BtreeIndexing::BtreeIndex & ftsIndex,
|
||||
sptr< ChunkedStorage::Reader > chunks,
|
||||
|
@ -149,11 +134,11 @@ public:
|
|||
searchString = gd::toQString( Folding::applyDiacriticsOnly( gd::toWString( searchString_ ) ) );
|
||||
|
||||
foundHeadwords = new QList< FTS::FtsHeadword >;
|
||||
QThreadPool::globalInstance()->start(
|
||||
new FTSResultsRequestRunnable( *this, hasExited ), -100 );
|
||||
results = 0;
|
||||
QThreadPool::globalInstance()->start( [ this ]() { this->run(); }, -100 );
|
||||
}
|
||||
|
||||
void run(); // Run from another thread by DslResourceRequestRunnable
|
||||
void run();
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
|
@ -165,7 +150,6 @@ public:
|
|||
isCancelled.ref();
|
||||
if( foundHeadwords )
|
||||
delete foundHeadwords;
|
||||
hasExited.acquire();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -351,27 +351,15 @@ void FullTextSearchDialog::accept()
|
|||
searchRegExp, mode,
|
||||
ui.matchCase->isChecked(),
|
||||
distanceBetweenWords,
|
||||
hasCJK ) )
|
||||
hasCJK, ignoreWordsOrder ) )
|
||||
{
|
||||
if( hasCJK && ( mode == WholeWords || mode == PlainText ) )
|
||||
{
|
||||
QMessageBox message( QMessageBox::Warning,
|
||||
"GoldenDict",
|
||||
tr( "CJK symbols in search string are not compatible with search modes \"Whole words\" and \"Plain text\"" ),
|
||||
QMessageBox::Ok,
|
||||
this );
|
||||
message.exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox message( QMessageBox::Warning,
|
||||
"GoldenDict",
|
||||
tr( "The search line must contains at least one word containing " )
|
||||
QMessageBox message( QMessageBox::Warning,
|
||||
"GoldenDict",
|
||||
tr( "The search line must contains at least one word containing " )
|
||||
+ QString::number( MinimumWordSize ) + tr( " or more symbols" ),
|
||||
QMessageBox::Ok,
|
||||
this );
|
||||
message.exec();
|
||||
}
|
||||
QMessageBox::Ok,
|
||||
this );
|
||||
message.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -393,6 +381,10 @@ void FullTextSearchDialog::accept()
|
|||
|
||||
for( unsigned x = 0; x < activeDicts.size(); ++x )
|
||||
{
|
||||
if( !activeDicts[ x ] ->haveFTSIndex())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
sptr< Dictionary::DataRequest > req = activeDicts[ x ]->getSearchResults(
|
||||
ui.searchLine->text(),
|
||||
mode,
|
||||
|
@ -621,7 +613,7 @@ Q_UNUSED( parent );
|
|||
for( int x = 0; x < hws.length(); x++ )
|
||||
{
|
||||
QList< FtsHeadword >::iterator it = std::lower_bound( headwords.begin(), headwords.end(), hws.at( x ) );
|
||||
if( it != headwords.end() )
|
||||
if( it != headwords.end() && *it == hws.at( x ) )
|
||||
{
|
||||
it->dictIDs.push_back( hws.at( x ).dictIDs.front() );
|
||||
for( QStringList::const_iterator itr = it->foundHiliteRegExps.constBegin();
|
||||
|
|
49
gddebug.cc
49
gddebug.cc
|
@ -4,61 +4,30 @@
|
|||
#include <QString>
|
||||
#include "gddebug.hh"
|
||||
#include <QDebug>
|
||||
#if(QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||
#if( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
|
||||
#include <QtCore5Compat/QTextCodec>
|
||||
#else
|
||||
#include <QTextCodec>
|
||||
#endif
|
||||
|
||||
QFile * logFilePtr;
|
||||
static QTextCodec * utf8Codec;
|
||||
|
||||
void gdWarning(const char *msg, ...)
|
||||
void gdWarning( const char * msg, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
QTextCodec *localeCodec = 0;
|
||||
|
||||
if( logFilePtr && logFilePtr->isOpen() )
|
||||
{
|
||||
if( utf8Codec == 0 )
|
||||
utf8Codec = QTextCodec::codecForName( "UTF8" );
|
||||
|
||||
localeCodec = QTextCodec::codecForLocale();
|
||||
QTextCodec::setCodecForLocale( utf8Codec );
|
||||
}
|
||||
va_list ap;
|
||||
va_start( ap, msg );
|
||||
|
||||
qWarning() << QString().vasprintf( msg, ap );
|
||||
|
||||
if( logFilePtr && logFilePtr->isOpen() )
|
||||
{
|
||||
QTextCodec::setCodecForLocale( localeCodec );
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
void gdDebug(const char *msg, ...)
|
||||
void gdDebug( const char * msg, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
// QTextCodec *localeCodec = 0;
|
||||
|
||||
// if( logFilePtr && logFilePtr->isOpen() )
|
||||
// {
|
||||
// if( utf8Codec == 0 )
|
||||
// utf8Codec = QTextCodec::codecForName( "UTF8" );
|
||||
|
||||
// localeCodec = QTextCodec::codecForLocale();
|
||||
// QTextCodec::setCodecForLocale( utf8Codec );
|
||||
// }
|
||||
va_list ap;
|
||||
va_start( ap, msg );
|
||||
|
||||
qDebug().noquote() << QString().vasprintf( msg, ap );
|
||||
|
||||
// if( logFilePtr && logFilePtr->isOpen() )
|
||||
// {
|
||||
// QTextCodec::setCodecForLocale( localeCodec );
|
||||
// }
|
||||
|
||||
va_end(ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
|
|
@ -20,13 +20,15 @@ Config::Preferences * GlobalBroadcaster::getPreference()
|
|||
return preference;
|
||||
}
|
||||
|
||||
void GlobalBroadcaster::addWhitelist(QString url){
|
||||
whitelist.push_back(url);
|
||||
auto baseUrl=::getHostBase(url);
|
||||
whitelist.push_back(baseUrl);
|
||||
void GlobalBroadcaster::addWhitelist( QString url )
|
||||
{
|
||||
whitelist.push_back( url );
|
||||
auto baseUrl = ::getHostBase( url );
|
||||
whitelist.push_back( baseUrl );
|
||||
}
|
||||
|
||||
bool GlobalBroadcaster::existedInWhitelist(QString url){
|
||||
return std::find(whitelist.begin(), whitelist.end(), url) != whitelist.end();
|
||||
bool GlobalBroadcaster::existedInWhitelist( QString url )
|
||||
{
|
||||
return std::find( whitelist.begin(), whitelist.end(), url ) != whitelist.end();
|
||||
}
|
||||
// namespace global
|
||||
|
|
|
@ -17,6 +17,7 @@ class GlobalBroadcaster : public QObject
|
|||
private:
|
||||
Config::Preferences * preference;
|
||||
std::vector<QString> whitelist;
|
||||
|
||||
public:
|
||||
void setPreference( Config::Preferences * _pre );
|
||||
Config::Preferences * getPreference();
|
||||
|
@ -24,6 +25,7 @@ public:
|
|||
void addWhitelist(QString host);
|
||||
bool existedInWhitelist(QString host);
|
||||
static GlobalBroadcaster * instance();
|
||||
|
||||
signals:
|
||||
void dictionaryChanges( ActiveDictIds ad );
|
||||
};
|
||||
|
|
16
gls.cc
16
gls.cc
|
@ -88,7 +88,7 @@ public:
|
|||
DEF_EX( exEncodingError, "Encoding error", Ex ) // Should never happen really
|
||||
|
||||
GlsScanner( string const & fileName ) ;
|
||||
~GlsScanner() throw();
|
||||
~GlsScanner() noexcept;
|
||||
|
||||
/// Returns the detected encoding of this file.
|
||||
Encoding getEncoding() const
|
||||
|
@ -293,7 +293,7 @@ bool GlsScanner::readNextLine( wstring & out, size_t & offset )
|
|||
}
|
||||
}
|
||||
|
||||
GlsScanner::~GlsScanner() throw()
|
||||
GlsScanner::~GlsScanner() noexcept
|
||||
{
|
||||
gzclose( f );
|
||||
}
|
||||
|
@ -372,16 +372,16 @@ public:
|
|||
|
||||
~GlsDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -425,7 +425,7 @@ public:
|
|||
}
|
||||
protected:
|
||||
|
||||
void loadIcon() throw();
|
||||
void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -517,7 +517,7 @@ GlsDictionary::~GlsDictionary()
|
|||
dict_data_close( dz );
|
||||
}
|
||||
|
||||
void GlsDictionary::loadIcon() throw()
|
||||
void GlsDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
|
@ -12,7 +12,28 @@ system(git describe --tags --always --dirty): hasGit=1
|
|||
!isEmpty(hasGit){
|
||||
GIT_HASH=$$system(git rev-parse --short=8 HEAD )
|
||||
}
|
||||
system(echo $${VERSION}.$${GIT_HASH} > version.txt)
|
||||
|
||||
win32{
|
||||
# date /T output is locale aware.
|
||||
DATE=$$system(date /T)
|
||||
}
|
||||
else{
|
||||
DATE=$$system(date '+%Y/%m/%d')
|
||||
}
|
||||
|
||||
system(echo $${VERSION}.$${GIT_HASH} on $${DATE} > version.txt)
|
||||
|
||||
!CONFIG( verbose_build_output ) {
|
||||
!win32|*-msvc* {
|
||||
# Reduce build log verbosity except for MinGW builds (mingw-make cannot
|
||||
# execute "@echo ..." commands inserted by qmake).
|
||||
CONFIG += silent
|
||||
}
|
||||
}
|
||||
|
||||
CONFIG( release, debug|release ) {
|
||||
DEFINES += NDEBUG
|
||||
}
|
||||
|
||||
# DEPENDPATH += . generators
|
||||
INCLUDEPATH += .
|
||||
|
@ -26,7 +47,8 @@ QT += core \
|
|||
webenginewidgets\
|
||||
webchannel\
|
||||
printsupport \
|
||||
help
|
||||
help \
|
||||
concurrent
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 5): QT += webenginecore core5compat
|
||||
|
||||
|
@ -42,11 +64,10 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
|
|||
DEFINES += MAKE_FFMPEG_PLAYER
|
||||
}
|
||||
|
||||
#QT += sql
|
||||
CONFIG += exceptions \
|
||||
rtti \
|
||||
stl \
|
||||
c++14 \
|
||||
c++17 \
|
||||
lrelease \
|
||||
embed_translations
|
||||
|
||||
|
@ -66,6 +87,8 @@ LIBS += \
|
|||
|
||||
CONFIG+=utf8_source
|
||||
|
||||
CONFIG+=force_debug_info
|
||||
|
||||
win32 {
|
||||
TARGET = GoldenDict
|
||||
|
||||
|
@ -76,13 +99,10 @@ win32 {
|
|||
DEFINES += NOMINMAX __WIN64
|
||||
}
|
||||
LIBS += -L$${PWD}/winlibs/lib/msvc
|
||||
QMAKE_CXXFLAGS += /wd4290 # silence the warning C4290: C++ exception specification ignored
|
||||
# silence the warning C4290: C++ exception specification ignored
|
||||
QMAKE_CXXFLAGS += /wd4290 /Zc:__cplusplus /std:c++17 /permissive-
|
||||
# QMAKE_LFLAGS_RELEASE += /OPT:REF /OPT:ICF
|
||||
# QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /DEBUG
|
||||
CONFIG+=force_debug_info
|
||||
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
|
||||
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
|
||||
DEFINES += GD_NO_MANIFEST
|
||||
|
||||
# QMAKE_CXXFLAGS_RELEASE += /GL # slows down the linking significantly
|
||||
LIBS += -lshell32 -luser32 -lsapi -lole32
|
||||
Debug: LIBS+= -lhunspelld
|
||||
|
@ -126,7 +146,6 @@ unix:!mac {
|
|||
DEFINES += HAVE_X11
|
||||
|
||||
lessThan(QT_MAJOR_VERSION, 6): QT += x11extras
|
||||
greaterThan(QT_MAJOR_VERSION, 5): QT += gui-private
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
|
||||
|
@ -141,9 +160,7 @@ unix:!mac {
|
|||
libavcodec \
|
||||
libswresample \
|
||||
}
|
||||
arm {
|
||||
#LIBS += -liconv
|
||||
} else {
|
||||
!arm {
|
||||
LIBS += -lX11 -lXtst
|
||||
}
|
||||
|
||||
|
@ -223,8 +240,10 @@ DEFINES += PROGRAM_VERSION=\\\"$$VERSION\\\"
|
|||
|
||||
# Input
|
||||
HEADERS += folding.hh \
|
||||
ankiconnector.h \
|
||||
article_inspect.h \
|
||||
articlewebpage.h \
|
||||
base/globalregex.hh \
|
||||
globalbroadcaster.h \
|
||||
iframeschemehandler.h \
|
||||
inc_case_folding.hh \
|
||||
|
@ -364,8 +383,10 @@ FORMS += groups.ui \
|
|||
fulltextsearch.ui
|
||||
|
||||
SOURCES += folding.cc \
|
||||
ankiconnector.cpp \
|
||||
article_inspect.cpp \
|
||||
articlewebpage.cpp \
|
||||
base/globalregex.cc \
|
||||
globalbroadcaster.cpp \
|
||||
iframeschemehandler.cpp \
|
||||
main.cc \
|
||||
|
@ -481,14 +502,11 @@ SOURCES += folding.cc \
|
|||
|
||||
win32 {
|
||||
FORMS += texttospeechsource.ui
|
||||
SOURCES += wordbyauto.cc \
|
||||
guids.c \
|
||||
SOURCES += guids.c \
|
||||
speechclient_win.cc \
|
||||
texttospeechsource.cc \
|
||||
speechhlp.cc
|
||||
HEADERS += wordbyauto.hh \
|
||||
uiauto.hh \
|
||||
texttospeechsource.hh \
|
||||
HEADERS += texttospeechsource.hh \
|
||||
sapi.hh \
|
||||
sphelper.hh \
|
||||
speechclient.hh \
|
||||
|
|
|
@ -468,10 +468,17 @@ void HotkeyWrapper::init()
|
|||
{
|
||||
keyToUngrab = grabbedKeys.end();
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
|
||||
// We use RECORD extension instead of XGrabKey. That's because XGrabKey
|
||||
// prevents other clients from getting their input if it's grabbed.
|
||||
|
||||
Display * display = QX11Info::display();
|
||||
Display * display = displayID;
|
||||
|
||||
lShiftCode = XKeysymToKeycode( display, XK_Shift_L );
|
||||
rShiftCode = XKeysymToKeycode( display, XK_Shift_R );
|
||||
|
@ -678,13 +685,25 @@ public:
|
|||
|
||||
~X11GrabUngrabErrorHandler()
|
||||
{
|
||||
XFlush( QX11Info::display() );
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
XFlush( displayID );
|
||||
(void) XSetErrorHandler( previousErrorHandler_ );
|
||||
}
|
||||
|
||||
bool isError() const
|
||||
{
|
||||
XFlush( QX11Info::display() );
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
XFlush( displayID );
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -706,8 +725,14 @@ HotkeyWrapper::GrabbedKeys::iterator HotkeyWrapper::grabKey( quint32 keyCode,
|
|||
|
||||
if ( result.second )
|
||||
{
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
X11GrabUngrabErrorHandler errorHandler;
|
||||
XGrabKey( QX11Info::display(), keyCode, modifiers, QX11Info::appRootWindow(),
|
||||
XGrabKey( displayID, keyCode, modifiers, DefaultRootWindow(displayID),
|
||||
True, GrabModeAsync, GrabModeAsync );
|
||||
|
||||
if ( errorHandler.isError() )
|
||||
|
@ -722,8 +747,14 @@ HotkeyWrapper::GrabbedKeys::iterator HotkeyWrapper::grabKey( quint32 keyCode,
|
|||
|
||||
void HotkeyWrapper::ungrabKey( GrabbedKeys::iterator i )
|
||||
{
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
X11GrabUngrabErrorHandler errorHandler;
|
||||
XUngrabKey( QX11Info::display(), i->first, i->second, QX11Info::appRootWindow() );
|
||||
XUngrabKey( displayID, i->first, i->second, XDefaultRootWindow(displayID) );
|
||||
|
||||
grabbedKeys.erase( i );
|
||||
|
||||
|
@ -746,14 +777,25 @@ quint32 HotkeyWrapper::nativeKey(int key)
|
|||
keySymName = QKeySequence( key ).toString();
|
||||
break;
|
||||
}
|
||||
|
||||
Display * display = QX11Info::display();
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
Display * display = displayID;
|
||||
return XKeysymToKeycode( display, XStringToKeysym( keySymName.toLatin1().data() ) );
|
||||
}
|
||||
|
||||
void HotkeyWrapper::unregister()
|
||||
{
|
||||
Display * display = QX11Info::display();
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
Display * display = displayID;
|
||||
|
||||
XRecordDisableContext( display, recordContext );
|
||||
XSync( display, False );
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/record.h>
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||
#include <QtGui/private/qtx11extras_p.h>
|
||||
#include <QGuiApplication>
|
||||
#else
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
|
23
howto/how to connect with anki.md
Normal file
23
howto/how to connect with anki.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# prerequisite
|
||||
1. install anki
|
||||
2. install ankiconnect
|
||||
|
||||
# configure anki
|
||||
## 1. the model must have `Front` and `Back` fields
|
||||
![Snipaste_2022-05-21_14-08-21](https://user-images.githubusercontent.com/105986/169638410-c6aa8038-df03-40de-8731-9f0b9f43bf59.png)
|
||||
## 2. configure the template
|
||||
the front template
|
||||
|
||||
![image](https://user-images.githubusercontent.com/105986/169638457-2358d020-0132-469f-a6b4-0fb6d1590fa2.png)
|
||||
the back template
|
||||
|
||||
![image](https://user-images.githubusercontent.com/105986/169638440-7191fcdd-c338-48a3-a899-7216a5c77425.png)
|
||||
|
||||
# configure goldendict
|
||||
## 1. through toolbar=>preference=>network
|
||||
![image](https://user-images.githubusercontent.com/105986/169657672-d1affbde-e80e-4110-8fd9-55f2645c5ee1.png)
|
||||
|
||||
## 2. action
|
||||
![image](https://user-images.githubusercontent.com/105986/169638740-abecde84-d33b-45ce-932c-d465c6650334.png)
|
||||
## 3. result
|
||||
![image](https://user-images.githubusercontent.com/105986/169638761-f67c009d-27cd-440d-bafa-ebbdce9577e3.png)
|
|
@ -149,7 +149,7 @@ QString unescape( QString const & str, bool saveFormat )
|
|||
{
|
||||
tmp.replace( QRegularExpression( "<(?:\\s*/?(?:div|h[1-6r]|q|p(?![alr])|br|li(?![ns])|td|blockquote|[uo]l|pre|d[dl]|nav|address))[^>]{0,}>",
|
||||
QRegularExpression::CaseInsensitiveOption ), " " );
|
||||
tmp.remove( QRegularExpression( "<[^>]*>" ) );
|
||||
tmp.replace( QRegularExpression( "<[^>]*>"), " ");
|
||||
|
||||
}
|
||||
return QTextDocumentFragment::fromHtml( tmp.trimmed() ).toPlainText();
|
||||
|
@ -157,6 +157,35 @@ QString unescape( QString const & str, bool saveFormat )
|
|||
return str;
|
||||
}
|
||||
|
||||
QString fromHtmlEscaped( QString const & str){
|
||||
QString retVal = str;
|
||||
QRegularExpression regExp("(?<lt>\\<\\;)|(?<gt>\\>\\;)|(?<amp>\\&\\;)|(?<quot>\\"\\;)", QRegularExpression::PatternOption::CaseInsensitiveOption);
|
||||
auto match = regExp.match(str, 0);
|
||||
|
||||
while (match.hasMatch())
|
||||
{
|
||||
if (!match.captured("lt").isEmpty())
|
||||
{
|
||||
retVal.replace(match.capturedStart("lt"), match.capturedLength("lt"), "<");
|
||||
}
|
||||
else if (!match.captured("gt").isEmpty())
|
||||
{
|
||||
retVal.replace(match.capturedStart("gt"), match.capturedLength("gt"), ">");
|
||||
}
|
||||
else if (!match.captured("amp").isEmpty())
|
||||
{
|
||||
retVal.replace(match.capturedStart("amp"), match.capturedLength("amp"), "&");
|
||||
}
|
||||
else if (!match.captured("quot").isEmpty())
|
||||
{
|
||||
retVal.replace(match.capturedStart("quot"), match.capturedLength("quot"), "\"");
|
||||
}
|
||||
match = regExp.match(retVal, match.capturedStart() + 1);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
string unescapeUtf8( const string &str, bool saveFormat )
|
||||
{
|
||||
return string( unescape( QString::fromUtf8( str.c_str(), str.size() ) ).toUtf8().data(), saveFormat );
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#ifndef __HTMLESCAPE_HH_INCLUDED__
|
||||
#define __HTMLESCAPE_HH_INCLUDED__
|
||||
|
||||
#include <QString>
|
||||
#include <string>
|
||||
|
||||
namespace Html {
|
||||
|
@ -24,6 +25,8 @@ string escapeForJavaScript( string const & );
|
|||
|
||||
// Replace html entities
|
||||
QString unescape( QString const & str, bool saveFormat = false );
|
||||
|
||||
QString fromHtmlEscaped( QString const & str);
|
||||
string unescapeUtf8( string const & str, bool saveFormat = false );
|
||||
|
||||
}
|
||||
|
|
16
hunspell.cc
16
hunspell.cc
|
@ -63,16 +63,16 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return name; }
|
||||
|
||||
virtual map< Property, string > getProperties() throw()
|
||||
virtual map< Property, string > getProperties() noexcept
|
||||
{ return map< Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual sptr< WordSearchRequest > prefixMatch( wstring const &,
|
||||
|
@ -91,11 +91,11 @@ public:
|
|||
virtual bool isLocalDictionary()
|
||||
{ return true; }
|
||||
|
||||
virtual vector< wstring > getAlternateWritings( const wstring & word ) throw();
|
||||
virtual vector< wstring > getAlternateWritings( const wstring & word ) noexcept;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -142,7 +142,7 @@ bool containsWhitespace( wstring const & str )
|
|||
return false;
|
||||
}
|
||||
|
||||
void HunspellDictionary::loadIcon() throw()
|
||||
void HunspellDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
@ -162,7 +162,7 @@ void HunspellDictionary::loadIcon() throw()
|
|||
dictionaryIconLoaded = true;
|
||||
}
|
||||
|
||||
vector< wstring > HunspellDictionary::getAlternateWritings( wstring const & word ) throw()
|
||||
vector< wstring > HunspellDictionary::getAlternateWritings( wstring const & word ) noexcept
|
||||
{
|
||||
vector< wstring > results;
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ bool IndexedZip::loadFile( uint32_t offset, vector< char > & data )
|
|||
|
||||
if ( !ZipFile::readLocalHeader( zip, header ) )
|
||||
{
|
||||
GD_DPRINTF( "Failed to load header\n" );
|
||||
GD_DPRINTF( "Failed to load header" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -73,13 +73,13 @@ bool IndexedZip::loadFile( uint32_t offset, vector< char > & data )
|
|||
switch( header.compressionMethod )
|
||||
{
|
||||
case ZipFile::Uncompressed:
|
||||
GD_DPRINTF( "Uncompressed\n" );
|
||||
GD_DPRINTF( "Uncompressed" );
|
||||
data.resize( header.uncompressedSize );
|
||||
return (size_t) zip.read( &data.front(), data.size() ) == data.size();
|
||||
|
||||
case ZipFile::Deflated:
|
||||
{
|
||||
GD_DPRINTF( "Deflated\n" );
|
||||
GD_DPRINTF( "Deflated" );
|
||||
|
||||
// Now do the deflation
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <windows.h>
|
||||
#elif defined(HAVE_X11)
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||
#include <QtGui/private/qtx11extras_p.h>
|
||||
#include <QGuiApplication>
|
||||
#else
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
@ -44,9 +44,17 @@ bool KeyboardState::checkModifiersPressed( int mask )
|
|||
( mask & Shift && !( keys & ( 1 << shiftKeyBit ) ) ) ||
|
||||
( mask & Win && !( keys & ( 1 << controlKeyBit ) ) ) );
|
||||
#else
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
|
||||
XkbStateRec state;
|
||||
|
||||
XkbGetState( QX11Info::display(), XkbUseCoreKbd, &state );
|
||||
XkbGetState( displayID, XkbUseCoreKbd, &state );
|
||||
|
||||
return !(
|
||||
( mask & Alt && !( state.base_mods & Mod1Mask ) ) ||
|
||||
|
|
|
@ -240,7 +240,7 @@ void LoadDictionaries::handlePath( Config::Path const & path )
|
|||
#endif
|
||||
}
|
||||
|
||||
void LoadDictionaries::indexingDictionary( string const & dictionaryName ) throw()
|
||||
void LoadDictionaries::indexingDictionary( string const & dictionaryName ) noexcept
|
||||
{
|
||||
emit indexingDictionarySignal( QString::fromUtf8( dictionaryName.c_str() ) );
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ signals:
|
|||
|
||||
public:
|
||||
|
||||
virtual void indexingDictionary( std::string const & dictionaryName ) throw();
|
||||
virtual void indexingDictionary( std::string const & dictionaryName ) noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -39,6 +39,20 @@
|
|||
<translation>(c) 2008-2013 Konstantin Isakov (ikm@goldendict.org)</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnkiConnector</name>
|
||||
<message>
|
||||
<location filename="../ankiconnector.cpp" line="56"/>
|
||||
<source>anki: post to anki failed</source>
|
||||
<translatorcomment>anki:发布成功</translatorcomment>
|
||||
<translation>anki:发布失败</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ankiconnector.cpp" line="76"/>
|
||||
<source>anki: post to anki success</source>
|
||||
<translation>anki: 发布成功</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ArticleInspector</name>
|
||||
<message>
|
||||
|
@ -315,7 +329,17 @@
|
|||
<translation>引用的音频播放程序不存在。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../articleview.cc" line="1971"/>
|
||||
<location filename="../articleview.cc" line="1853"/>
|
||||
<source>Save &Bookmark "%1..."</source>
|
||||
<translation>保存为书签(&S)“%1...”</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../articleview.cc" line="1861"/>
|
||||
<source>&Send "%1" to anki with selected text.</source>
|
||||
<translation>将“%1”发送到anki并附带选择的文本。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../articleview.cc" line="2016"/>
|
||||
<source>Sound files (*.wav *.ogg *.oga *.mp3 *.mp4 *.aac *.flac *.mid *.wv *.ape);;All files (*.*)</source>
|
||||
<translation>声音文件(*.wav *.ogg *.oga *.mp3 *.mp4 *.aac *.flac *.mid *.wv *.ape);;所有文件(*.*)</translation>
|
||||
</message>
|
||||
|
@ -3903,7 +3927,27 @@ however, the article from the topmost dictionary is shown.</source>
|
|||
<translation>自定义设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../preferences.ui" line="1147"/>
|
||||
<location filename="../preferences.ui" line="1087"/>
|
||||
<source>Anki Connect</source>
|
||||
<translation>Anki连接</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../preferences.ui" line="1108"/>
|
||||
<source>http://</source>
|
||||
<translation>http://</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../preferences.ui" line="1152"/>
|
||||
<source>Deck:</source>
|
||||
<translation>牌组:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../preferences.ui" line="1162"/>
|
||||
<source>Model:</source>
|
||||
<translation>模板:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../preferences.ui" line="1214"/>
|
||||
<source>Some sites detect GoldenDict via HTTP headers and block the requests.
|
||||
Enable this option to workaround the problem.</source>
|
||||
<translation>部分网站屏蔽了使用 GoldenDict 浏览器标识(UA)的请求,启用此选项以绕过该问题。</translation>
|
||||
|
@ -4420,6 +4464,12 @@ from Stardict, Babylon and GLS dictionaries</source>
|
|||
<source>Date: %1%2</source>
|
||||
<translation>日期:%1%2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ankiconnector.cpp" line="55"/>
|
||||
<location filename="../ankiconnector.cpp" line="69"/>
|
||||
<source>anki: post to anki failed</source>
|
||||
<translation>anki:发布失败</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QuickFilterLine</name>
|
||||
|
|
14
lsa.cc
14
lsa.cc
|
@ -164,15 +164,15 @@ public:
|
|||
LsaDictionary( string const & id, string const & indexFile,
|
||||
vector< string > const & dictionaryFiles );
|
||||
|
||||
virtual string getName() throw();
|
||||
virtual string getName() noexcept;
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.soundsCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return getArticleCount(); }
|
||||
|
||||
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
|
||||
|
@ -186,10 +186,10 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
};
|
||||
|
||||
string LsaDictionary::getName() throw()
|
||||
string LsaDictionary::getName() noexcept
|
||||
{
|
||||
string result = FsEncoding::basename( getDictionaryFilenames()[ 0 ] );
|
||||
|
||||
|
@ -498,7 +498,7 @@ sptr< Dictionary::DataRequest > LsaDictionary::getResource( string const & name
|
|||
return dr;
|
||||
}
|
||||
|
||||
void LsaDictionary::loadIcon() throw()
|
||||
void LsaDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
2
main.cc
2
main.cc
|
@ -253,7 +253,7 @@ int main( int argc, char ** argv )
|
|||
|
||||
#endif
|
||||
|
||||
QStringList localSchemes={"gdlookup","gdau","gico","qrcx","bres","bword","gdprg","gdvideo","gdpicture","gdtts","ifr"};
|
||||
QStringList localSchemes={"gdlookup","gdau","gico","qrcx","bres","bword","gdprg","gdvideo","gdpicture","gdtts","ifr", "entry"};
|
||||
|
||||
for (int i = 0; i < localSchemes.size(); ++i)
|
||||
{
|
||||
|
|
101
mainwindow.cc
101
mainwindow.cc
|
@ -60,9 +60,12 @@
|
|||
#include "wstring_qt.hh"
|
||||
#endif
|
||||
|
||||
#include <QWebEngineSettings>
|
||||
#include <QWebEngineProfile>
|
||||
|
||||
#ifdef HAVE_X11
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||
#include <QtGui/private/qtx11extras_p.h>
|
||||
#include <QGuiApplication>
|
||||
#else
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
@ -90,6 +93,19 @@ class InitSSLRunnable : public QRunnable
|
|||
|
||||
#endif
|
||||
|
||||
void MainWindow::changeWebEngineViewFont()
|
||||
{
|
||||
if( cfg.preferences.webFontFamily.isEmpty() )
|
||||
{
|
||||
QWebEngineProfile::defaultProfile()->settings()->resetFontFamily( QWebEngineSettings::StandardFont );
|
||||
}
|
||||
else
|
||||
{
|
||||
QWebEngineProfile::defaultProfile()->settings()->setFontFamily( QWebEngineSettings::StandardFont,
|
||||
cfg.preferences.webFontFamily );
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::MainWindow( Config::Class & cfg_ ):
|
||||
trayIcon( 0 ),
|
||||
groupLabel( &searchPaneTitleBar ),
|
||||
|
@ -148,6 +164,7 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
|||
localSchemeHandler = new LocalSchemeHandler( articleNetMgr );
|
||||
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler( "gdlookup", localSchemeHandler );
|
||||
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler( "bword", localSchemeHandler );
|
||||
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler( "entry", localSchemeHandler );
|
||||
|
||||
iframeSchemeHandler = new IframeSchemeHandler( this );
|
||||
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler( "ifr", iframeSchemeHandler );
|
||||
|
@ -761,6 +778,9 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
|||
|
||||
applyProxySettings();
|
||||
|
||||
//set webengineview font
|
||||
changeWebEngineViewFont();
|
||||
|
||||
connect( &dictNetMgr, SIGNAL( proxyAuthenticationRequired( QNetworkProxy, QAuthenticator * ) ),
|
||||
this, SLOT( proxyAuthentication( QNetworkProxy, QAuthenticator * ) ) );
|
||||
|
||||
|
@ -1225,6 +1245,10 @@ void MainWindow::closeEvent( QCloseEvent * ev )
|
|||
|
||||
void MainWindow::quitApp()
|
||||
{
|
||||
if( inspector && inspector->isVisible() )
|
||||
{
|
||||
inspector->close();
|
||||
}
|
||||
commitData();
|
||||
qApp->quit();
|
||||
}
|
||||
|
@ -1393,6 +1417,7 @@ void MainWindow::updateGroupList()
|
|||
|
||||
groupList->fill( groupInstances );
|
||||
groupList->setCurrentGroup( cfg.lastMainGroupId );
|
||||
|
||||
updateCurrentGroupProperty();
|
||||
|
||||
updateDictionaryBar();
|
||||
|
@ -1612,9 +1637,10 @@ ArticleView * MainWindow::createNewTab( bool switchToIt,
|
|||
groupList );
|
||||
|
||||
connect( view, &ArticleView::inspectSignal,this,[this](QWebEngineView * view){
|
||||
if(inspector){
|
||||
inspector->setInspectPage(view);
|
||||
if( !inspector ){
|
||||
inspector = new ArticleInspector( this );
|
||||
}
|
||||
inspector->setInspectPage( view );
|
||||
});
|
||||
|
||||
connect( view, SIGNAL( titleChanged( ArticleView *, QString const & ) ),
|
||||
|
@ -1666,6 +1692,7 @@ ArticleView * MainWindow::createNewTab( bool switchToIt,
|
|||
connect( view, SIGNAL( zoomIn()), this, SLOT( zoomin() ) );
|
||||
|
||||
connect( view, SIGNAL( zoomOut()), this, SLOT( zoomout() ) );
|
||||
connect( view, &ArticleView::saveBookmarkSignal, this, &MainWindow::addBookmarkToFavorite );
|
||||
|
||||
view->setSelectionBySingleClick( cfg.preferences.selectWordBySingleClick );
|
||||
|
||||
|
@ -2790,10 +2817,6 @@ void MainWindow::showTranslationFor( Config::InputPhrase const & phrase,
|
|||
|
||||
view->showDefinition( phrase, group, scrollTo );
|
||||
|
||||
updatePronounceAvailability();
|
||||
updateFoundInDictsList();
|
||||
|
||||
updateBackForwardButtons();
|
||||
|
||||
//ui.tabWidget->setTabText( ui.tabWidget->indexOf(ui.tab), inWord.trimmed() );
|
||||
}
|
||||
|
@ -2815,11 +2838,6 @@ void MainWindow::showTranslationFor( QString const & inWord,
|
|||
view->showDefinition( inWord, dictIDs, searchRegExp,
|
||||
groupInstances[ groupList->currentIndex() ].id,
|
||||
ignoreDiacritics );
|
||||
|
||||
updatePronounceAvailability();
|
||||
updateFoundInDictsList();
|
||||
|
||||
updateBackForwardButtons();
|
||||
}
|
||||
|
||||
#ifdef HAVE_X11
|
||||
|
@ -2889,9 +2907,15 @@ void MainWindow::toggleMainWindow( bool onlyShow )
|
|||
|
||||
focusTranslateLine();
|
||||
#ifdef HAVE_X11
|
||||
#if QT_VERSION < 0x060000
|
||||
Display *displayID = QX11Info::display();
|
||||
#else
|
||||
QNativeInterface::QX11Application *x11AppInfo = qApp->nativeInterface<QNativeInterface::QX11Application>();
|
||||
Display *displayID = x11AppInfo->display();
|
||||
#endif
|
||||
Window wh = 0;
|
||||
int rev = 0;
|
||||
XGetInputFocus( QX11Info::display(), &wh, &rev );
|
||||
XGetInputFocus( displayID, &wh, &rev );
|
||||
if( wh != translateLine->internalWinId() && !byIconClick )
|
||||
{
|
||||
QPoint p( 1, 1 );
|
||||
|
@ -2904,17 +2928,17 @@ void MainWindow::toggleMainWindow( bool onlyShow )
|
|||
event.xbutton.x_root = p.x();
|
||||
event.xbutton.y_root = p.y();
|
||||
event.xbutton.window = internalWinId();
|
||||
event.xbutton.root = QX11Info::appRootWindow( QX11Info::appScreen() );
|
||||
event.xbutton.root = XDefaultRootWindow(displayID);
|
||||
event.xbutton.state = Button1Mask;
|
||||
event.xbutton.button = Button1;
|
||||
event.xbutton.same_screen = true;
|
||||
event.xbutton.time = CurrentTime;
|
||||
|
||||
XSendEvent( QX11Info::display(), internalWinId(), true, 0xfff, &event );
|
||||
XFlush( QX11Info::display() );
|
||||
XSendEvent( displayID, internalWinId(), true, 0xfff, &event );
|
||||
XFlush( displayID );
|
||||
event.type = ButtonRelease;
|
||||
XSendEvent( QX11Info::display(), internalWinId(), true, 0xfff, &event );
|
||||
XFlush( QX11Info::display() );
|
||||
XSendEvent( displayID, internalWinId(), true, 0xfff, &event );
|
||||
XFlush( displayID );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -2966,7 +2990,19 @@ void MainWindow::hotKeyActivated( int hk )
|
|||
toggleMainWindow();
|
||||
else
|
||||
if ( scanPopup.get() )
|
||||
{
|
||||
#ifdef HAVE_X11
|
||||
// When the user requests translation with the Ctrl+C+C hotkey in certain apps
|
||||
// on some GNU/Linux systems, GoldenDict appears to handle Ctrl+C+C before the
|
||||
// active application finishes handling Ctrl+C. As a result, GoldenDict finds
|
||||
// the clipboard empty, silently cancels the translation request, and users report
|
||||
// that Ctrl+C+C is broken in these apps. Slightly delay handling the clipboard
|
||||
// hotkey to give the active application more time and thus work around the issue.
|
||||
QTimer::singleShot( 10, scanPopup.get(), SLOT( translateWordFromClipboard() ) );
|
||||
#else
|
||||
scanPopup->translateWordFromClipboard();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::prepareNewReleaseChecks()
|
||||
|
@ -3470,7 +3506,7 @@ void MainWindow::on_saveArticle_triggered()
|
|||
// MDict anchors
|
||||
QRegularExpression anchorLinkRe(
|
||||
"(<\\s*a\\s+[^>]*\\b(?:name|id)\\b\\s*=\\s*[\"']*g[0-9a-f]{32}_)([0-9a-f]+_)(?=[^\"'])",
|
||||
QRegularExpression::PatternOption::CaseInsensitiveOption );
|
||||
QRegularExpression::PatternOption::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption );
|
||||
html.replace( anchorLinkRe, "\\1" );
|
||||
|
||||
if( complete )
|
||||
|
@ -4623,6 +4659,15 @@ void MainWindow::addWordToFavorites( QString const & word, unsigned groupId )
|
|||
ui.favoritesPaneWidget->addHeadword( folder, word );
|
||||
}
|
||||
|
||||
void MainWindow::addBookmarkToFavorite( QString const & text )
|
||||
{
|
||||
// get current tab word.
|
||||
QString word = unescapeTabHeader( ui.tabWidget->tabText( ui.tabWidget->currentIndex() ) );
|
||||
const auto bookmark = QString( "%1~~~%2" ).arg( word, text );
|
||||
|
||||
ui.favoritesPaneWidget->addHeadword( nullptr, bookmark );
|
||||
}
|
||||
|
||||
void MainWindow::addAllTabsToFavorites()
|
||||
{
|
||||
QString folder;
|
||||
|
@ -4695,8 +4740,22 @@ void MainWindow::headwordFromFavorites( QString const & headword,
|
|||
}
|
||||
|
||||
// Show headword without lost of focus on Favorites tree
|
||||
setTranslateBoxTextAndClearSuffix( headword, EscapeWildcards, DisablePopup );
|
||||
showTranslationFor(headword );
|
||||
// bookmark cases: the favorite item may like this "word~~~selectedtext"
|
||||
auto words = headword.split( "~~~" );
|
||||
|
||||
setTranslateBoxTextAndClearSuffix( words[0], EscapeWildcards, DisablePopup );
|
||||
|
||||
//must be a bookmark.
|
||||
if(words.size()>1)
|
||||
{
|
||||
auto view = getCurrentArticleView();
|
||||
if(view)
|
||||
{
|
||||
view->setDelayedHighlightText(words[1]);// findText( words[ 1 ], QWebEnginePage::FindCaseSensitively );
|
||||
}
|
||||
}
|
||||
|
||||
showTranslationFor( words[ 0 ] );
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
|
|
|
@ -260,6 +260,8 @@ private:
|
|||
TranslateBoxPopup popupAction );
|
||||
void setTranslateBoxTextAndClearSuffix( QString const & text, WildcardPolicy wildcardPolicy,
|
||||
TranslateBoxPopup popupAction );
|
||||
void changeWebEngineViewFont();
|
||||
|
||||
private slots:
|
||||
|
||||
void hotKeyActivated( int );
|
||||
|
@ -460,6 +462,8 @@ private slots:
|
|||
|
||||
void addWordToFavorites( QString const & word, unsigned groupId );
|
||||
|
||||
void addBookmarkToFavorite( QString const & text );
|
||||
|
||||
bool isWordPresentedInFavorites( QString const & word, unsigned groupId );
|
||||
|
||||
void sendWordToInputLine( QString const & word );
|
||||
|
|
|
@ -336,6 +336,26 @@ bool MdictParser::readHeader( QDataStream & in )
|
|||
headerTextUtf16.clear();
|
||||
in.setByteOrder( QDataStream::BigEndian );
|
||||
|
||||
|
||||
//parse stylesheet
|
||||
QString styleSheets;
|
||||
|
||||
if( headerText.contains( "StyleSheet" ) )
|
||||
{
|
||||
// a workaround to bypass https://bugreports.qt.io/browse/QTBUG-102612
|
||||
QRegularExpression rx( "StyleSheet=\"([^\"]*?)\"", QRegularExpression::CaseInsensitiveOption );
|
||||
|
||||
auto match = rx.match( headerText );
|
||||
|
||||
if( match.hasMatch() || match.hasPartialMatch() )
|
||||
{
|
||||
styleSheets = match.captured( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//with this control character ,qt6.x can not parse attribute value.
|
||||
headerText.remove(QRegularExpression("\\p{C}"));
|
||||
|
||||
QDomNamedNodeMap headerAttributes = parseHeaderAttributes( headerText );
|
||||
|
||||
encoding_ = headerAttributes.namedItem( "Encoding" ).toAttr().value();
|
||||
|
@ -352,32 +372,14 @@ bool MdictParser::readHeader( QDataStream & in )
|
|||
// styleId # 1-255
|
||||
// style.prefix
|
||||
// style.suffix
|
||||
if ( headerAttributes.contains( "StyleSheet" ) )
|
||||
if ( !styleSheets.isEmpty() )
|
||||
{
|
||||
#if( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
|
||||
//a workaround to bypass https://bugreports.qt.io/browse/QTBUG-102612
|
||||
QRegularExpression rx( "StyleSheet=\"([^\"]*?)\"", QRegularExpression::CaseInsensitiveOption );
|
||||
|
||||
auto match = rx.match( headerText );
|
||||
QString styleSheets;
|
||||
|
||||
if( match.hasMatch() || match.hasPartialMatch() )
|
||||
{
|
||||
styleSheets = match.captured( 1 );
|
||||
}
|
||||
#else
|
||||
QString styleSheets = headerAttributes.namedItem( "StyleSheet" ).toAttr().value();
|
||||
#endif
|
||||
QStringList lines = styleSheets.split( QRegularExpression( "[\r\n]" ), Qt::KeepEmptyParts );
|
||||
|
||||
for( int i = 0; i < lines.size() - 3; i += 3 )
|
||||
{
|
||||
#if( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
|
||||
styleSheets_[ lines[ i ].toInt() ] =
|
||||
pair< QString, QString >( Html::unescape( lines[ i + 1 ] ), Html::unescape( lines[ i + 2 ] ) );
|
||||
#else
|
||||
styleSheets_[ lines[ i ].toInt() ] = pair< QString, QString >( lines[ i + 1 ], lines[ i + 2 ] );
|
||||
#endif
|
||||
pair( Html::fromHtmlEscaped( lines[ i + 1 ] ), Html::fromHtmlEscaped( lines[ i + 2 ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ public:
|
|||
{
|
||||
QString s = QString::fromUtf8( article.c_str() );
|
||||
substituteStylesheet( s, styleSheets );
|
||||
return string( s.toUtf8().constData() );
|
||||
return s.toStdString();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
139
mdx.cc
139
mdx.cc
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include "tiff.hh"
|
||||
#include "utils.hh"
|
||||
#include "base/globalregex.hh"
|
||||
|
||||
namespace Mdx
|
||||
{
|
||||
|
@ -162,7 +163,7 @@ public:
|
|||
|
||||
MdictParser::RecordInfo indexEntry;
|
||||
vector< char > chunk;
|
||||
Mutex::Lock _( idxMutex );
|
||||
// Mutex::Lock _( idxMutex );
|
||||
const char * indexEntryPtr = chunks.getBlock( links[ 0 ].articleOffset, chunk );
|
||||
memcpy( &indexEntry, indexEntryPtr, sizeof( indexEntry ) );
|
||||
|
||||
|
@ -192,51 +193,6 @@ public:
|
|||
|
||||
};
|
||||
|
||||
struct MdxRegex
|
||||
{
|
||||
MdxRegex() :
|
||||
allLinksRe( "(?:<\\s*(a(?:rea)?|img|link|script|source)(?:\\s+[^>]+|\\s*)>)",
|
||||
QRegularExpression::CaseInsensitiveOption ),
|
||||
wordCrossLink( "([\\s\"']href\\s*=)\\s*([\"'])entry://([^>#]*?)((?:#[^>]*?)?)\\2",
|
||||
QRegularExpression::CaseInsensitiveOption ),
|
||||
anchorIdRe( "([\\s\"'](?:name|id)\\s*=)\\s*([\"'])\\s*(?=\\S)", QRegularExpression::CaseInsensitiveOption ),
|
||||
anchorIdReWord( "([\\s\"'](?:name|id)\\s*=)\\s*([\"'])\\s*(?=\\S)([^\"]*)", QRegularExpression::CaseInsensitiveOption ),
|
||||
anchorIdRe2( "([\\s\"'](?:name|id)\\s*=)\\s*(?=[^\"'])([^\\s\">]+)", QRegularExpression::CaseInsensitiveOption ),
|
||||
anchorLinkRe( "([\\s\"']href\\s*=\\s*[\"'])entry://#", QRegularExpression::CaseInsensitiveOption ),
|
||||
audioRe( "([\\s\"']href\\s*=)\\s*([\"'])sound://([^\">]+)\\2",
|
||||
QRegularExpression::CaseInsensitiveOption | QRegularExpression::InvertedGreedinessOption ),
|
||||
stylesRe( "([\\s\"']href\\s*=)\\s*([\"'])(?!\\s*\\b(?:(?:bres|https?|ftp)://"
|
||||
"|(?:data|javascript):))(?:file://)?[\\x00-\\x1f\\x7f]*\\.*/?([^\">]+)\\2",
|
||||
QRegularExpression::CaseInsensitiveOption ),
|
||||
stylesRe2( "([\\s\"']href\\s*=)\\s*(?![\\s\"']|\\b(?:(?:bres|https?|ftp)://"
|
||||
"|(?:data|javascript):))(?:file://)?[\\x00-\\x1f\\x7f]*\\.*/?([^\\s\">]+)",
|
||||
QRegularExpression::CaseInsensitiveOption ),
|
||||
inlineScriptRe( "<\\s*script(?:(?=\\s)(?:(?![\\s\"']src\\s*=)[^>])+|\\s*)>",
|
||||
QRegularExpression::CaseInsensitiveOption ),
|
||||
closeScriptTagRe( "<\\s*/script\\s*>", QRegularExpression::CaseInsensitiveOption ),
|
||||
srcRe( "([\\s\"']src\\s*=)\\s*([\"'])(?!\\s*\\b(?:(?:bres|https?|ftp)://"
|
||||
"|(?:data|javascript):))(?:file://)?[\\x00-\\x1f\\x7f]*\\.*/?([^\">]+)\\2",
|
||||
QRegularExpression::CaseInsensitiveOption ),
|
||||
srcRe2( "([\\s\"']src\\s*=)\\s*(?![\\s\"']|\\b(?:(?:bres|https?|ftp)://"
|
||||
"|(?:data|javascript):))(?:file://)?[\\x00-\\x1f\\x7f]*\\.*/?([^\\s\">]+)",
|
||||
QRegularExpression::CaseInsensitiveOption )
|
||||
{
|
||||
}
|
||||
QRegularExpression allLinksRe;
|
||||
QRegularExpression wordCrossLink;
|
||||
QRegularExpression anchorIdRe;
|
||||
QRegularExpression anchorIdReWord;
|
||||
QRegularExpression anchorIdRe2;
|
||||
QRegularExpression anchorLinkRe;
|
||||
QRegularExpression audioRe;
|
||||
QRegularExpression stylesRe;
|
||||
QRegularExpression stylesRe2;
|
||||
QRegularExpression inlineScriptRe;
|
||||
QRegularExpression closeScriptTagRe;
|
||||
QRegularExpression srcRe;
|
||||
QRegularExpression srcRe2;
|
||||
};
|
||||
|
||||
class MdxDictionary: public BtreeIndexing::BtreeDictionary
|
||||
{
|
||||
Mutex idxMutex;
|
||||
|
@ -256,8 +212,6 @@ class MdxDictionary: public BtreeIndexing::BtreeDictionary
|
|||
string initError;
|
||||
QString cacheDirName;
|
||||
|
||||
static MdxRegex mdxRx;
|
||||
|
||||
public:
|
||||
|
||||
MdxDictionary( string const & id, string const & indexFile, vector<string> const & dictionaryFiles );
|
||||
|
@ -266,22 +220,22 @@ public:
|
|||
|
||||
virtual void deferredInit();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{
|
||||
return dictionaryName;
|
||||
}
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{
|
||||
return map< Dictionary::Property, string >();
|
||||
}
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{
|
||||
return idxHeader.articleCount;
|
||||
}
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{
|
||||
return idxHeader.wordCount;
|
||||
}
|
||||
|
@ -327,7 +281,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -347,8 +301,6 @@ private:
|
|||
friend class MddResourceRequest;
|
||||
};
|
||||
|
||||
MdxRegex MdxDictionary::mdxRx;
|
||||
|
||||
MdxDictionary::MdxDictionary( string const & id, string const & indexFile,
|
||||
vector<string> const & dictionaryFiles ):
|
||||
BtreeDictionary( id, dictionaryFiles ),
|
||||
|
@ -847,14 +799,14 @@ void MddResourceRequest::run()
|
|||
{
|
||||
QString css = QString::fromUtf8( data.data(), data.size() );
|
||||
|
||||
QRegularExpression links( "url\\(\\s*(['\"]?)([^'\"]*)(['\"]?)\\s*\\)",
|
||||
QRegularExpression::CaseInsensitiveOption );
|
||||
// QRegularExpression links( "url\\(\\s*(['\"]?)([^'\"]*)(['\"]?)\\s*\\)",
|
||||
// QRegularExpression::CaseInsensitiveOption );
|
||||
|
||||
QString id = QString::fromUtf8( dict.getId().c_str() );
|
||||
int pos = 0;
|
||||
|
||||
QString newCSS;
|
||||
QRegularExpressionMatchIterator it = links.globalMatch( css );
|
||||
QRegularExpressionMatchIterator it = RX::Mdx::links.globalMatch( css );
|
||||
while ( it.hasNext() )
|
||||
{
|
||||
QRegularExpressionMatch match = it.next();
|
||||
|
@ -915,7 +867,7 @@ const QString & MdxDictionary::getDescription()
|
|||
}
|
||||
else
|
||||
{
|
||||
Mutex::Lock _( idxMutex );
|
||||
// Mutex::Lock _( idxMutex );
|
||||
vector< char > chunk;
|
||||
char * dictDescription = chunks.getBlock( idxHeader.descriptionAddress, chunk );
|
||||
string str( dictDescription );
|
||||
|
@ -925,7 +877,7 @@ const QString & MdxDictionary::getDescription()
|
|||
return dictionaryDescription;
|
||||
}
|
||||
|
||||
void MdxDictionary::loadIcon() throw()
|
||||
void MdxDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
@ -948,7 +900,7 @@ void MdxDictionary::loadIcon() throw()
|
|||
void MdxDictionary::loadArticle( uint32_t offset, string & articleText, bool noFilter )
|
||||
{
|
||||
vector< char > chunk;
|
||||
Mutex::Lock _( idxMutex );
|
||||
// Mutex::Lock _( idxMutex );
|
||||
|
||||
// Load record info from index
|
||||
MdictParser::RecordInfo recordInfo;
|
||||
|
@ -959,25 +911,32 @@ void MdxDictionary::loadArticle( uint32_t offset, string & articleText, bool noF
|
|||
QString articleId;
|
||||
articleId.setNum( ( quint64 )pRecordInfo, 16 );
|
||||
|
||||
ScopedMemMap compressed( dictFile, recordInfo.compressedBlockPos, recordInfo.compressedBlockSize );
|
||||
if ( !compressed.startAddress() )
|
||||
throw exCorruptDictionary();
|
||||
|
||||
QByteArray decompressed;
|
||||
if ( !MdictParser::parseCompressedBlock( recordInfo.compressedBlockSize, ( char * )compressed.startAddress(),
|
||||
recordInfo.decompressedBlockSize, decompressed ) )
|
||||
throw exCorruptDictionary();
|
||||
|
||||
{
|
||||
Mutex::Lock _( idxMutex );
|
||||
ScopedMemMap compressed( dictFile, recordInfo.compressedBlockPos, recordInfo.compressedBlockSize );
|
||||
if( !compressed.startAddress() )
|
||||
throw exCorruptDictionary();
|
||||
|
||||
if( !MdictParser::parseCompressedBlock( recordInfo.compressedBlockSize,
|
||||
(char *)compressed.startAddress(),
|
||||
recordInfo.decompressedBlockSize,
|
||||
decompressed ) )
|
||||
throw exCorruptDictionary();
|
||||
}
|
||||
|
||||
QString article = MdictParser::toUtf16( encoding.c_str(),
|
||||
decompressed.constData() + recordInfo.recordOffset,
|
||||
recordInfo.recordSize );
|
||||
|
||||
article = MdictParser::substituteStylesheet( article, styleSheets );
|
||||
|
||||
if( !noFilter )
|
||||
{
|
||||
article = MdictParser::substituteStylesheet( article, styleSheets );
|
||||
article = filterResource( articleId, article );
|
||||
}
|
||||
|
||||
articleText = string( article.toUtf8().constData() );
|
||||
articleText = article.toStdString();
|
||||
}
|
||||
|
||||
QString & MdxDictionary::filterResource( QString const & articleId, QString & article )
|
||||
|
@ -987,7 +946,7 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
|
||||
QString articleNewText;
|
||||
int linkPos = 0;
|
||||
QRegularExpressionMatchIterator it = mdxRx.allLinksRe.globalMatch( article );
|
||||
QRegularExpressionMatchIterator it = RX::Mdx::allLinksRe.globalMatch( article );
|
||||
QMap<QString,QString> idMap;
|
||||
while( it.hasNext() )
|
||||
{
|
||||
|
@ -1005,10 +964,10 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
|
||||
if( !linkType.isEmpty() && linkType.at( 0 ) == 'a' )
|
||||
{
|
||||
QRegularExpressionMatch match = mdxRx.anchorIdRe.match( linkTxt );
|
||||
QRegularExpressionMatch match = RX::Mdx::anchorIdRe.match( linkTxt );
|
||||
if( match.hasMatch() )
|
||||
{
|
||||
auto wordMatch = mdxRx.anchorIdReWord.match( linkTxt );
|
||||
auto wordMatch = RX::Mdx::anchorIdReWord.match( linkTxt );
|
||||
if( wordMatch.hasMatch() )
|
||||
{
|
||||
idMap.insert( wordMatch.captured( 3 ), uniquePrefix + wordMatch.captured( 3 ) );
|
||||
|
@ -1017,11 +976,11 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
||||
}
|
||||
else
|
||||
newLink = linkTxt.replace( mdxRx.anchorIdRe2, "\\1\"" + uniquePrefix + "\\2\"" );
|
||||
newLink = linkTxt.replace( RX::Mdx::anchorIdRe2, "\\1\"" + uniquePrefix + "\\2\"" );
|
||||
|
||||
newLink = newLink.replace( mdxRx.anchorLinkRe, "\\1#" + uniquePrefix );
|
||||
newLink = newLink.replace( RX::Mdx::anchorLinkRe, "\\1#" + uniquePrefix );
|
||||
|
||||
match = mdxRx.audioRe.match( newLink );
|
||||
match = RX::Mdx::audioRe.match( newLink );
|
||||
if( match.hasMatch() )
|
||||
{
|
||||
// sounds and audio link script
|
||||
|
@ -1032,7 +991,7 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
+ newLink.replace( match.capturedStart(), match.capturedLength(), newTxt );
|
||||
}
|
||||
|
||||
match = mdxRx.wordCrossLink.match( newLink );
|
||||
match = RX::Mdx::wordCrossLink.match( newLink );
|
||||
if( match.hasMatch() )
|
||||
{
|
||||
QString newTxt = match.captured( 1 ) + match.captured( 2 )
|
||||
|
@ -1050,7 +1009,7 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
if( linkType.compare( "link" ) == 0 )
|
||||
{
|
||||
// stylesheets
|
||||
QRegularExpressionMatch match = mdxRx.stylesRe.match( linkTxt );
|
||||
QRegularExpressionMatch match = RX::Mdx::stylesRe.match( linkTxt );
|
||||
if( match.hasMatch() )
|
||||
{
|
||||
QString newText = match.captured( 1 ) + match.captured( 2 )
|
||||
|
@ -1059,7 +1018,7 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
||||
}
|
||||
else
|
||||
newLink = linkTxt.replace( mdxRx.stylesRe2,
|
||||
newLink = linkTxt.replace( RX::Mdx::stylesRe2,
|
||||
"\\1\"bres://" + id + "/\\2\"" );
|
||||
}
|
||||
else
|
||||
|
@ -1067,13 +1026,13 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
|| linkType.compare( "source" ) == 0 )
|
||||
{
|
||||
// javascripts and images
|
||||
QRegularExpressionMatch match = mdxRx.inlineScriptRe.match( linkTxt );
|
||||
QRegularExpressionMatch match = RX::Mdx::inlineScriptRe.match( linkTxt );
|
||||
if( linkType.at( 1 ) == 'c' // "script" tag
|
||||
&& match.hasMatch() && match.capturedLength() == linkTxt.length() )
|
||||
{
|
||||
// skip inline scripts
|
||||
articleNewText += linkTxt;
|
||||
match = mdxRx.closeScriptTagRe.match( article, linkPos );
|
||||
match = RX::Mdx::closeScriptTagRe.match( article, linkPos );
|
||||
if( match.hasMatch() )
|
||||
{
|
||||
articleNewText += article.mid( linkPos, match.capturedEnd() - linkPos );
|
||||
|
@ -1083,7 +1042,7 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
}
|
||||
else
|
||||
{
|
||||
match = mdxRx.srcRe.match( linkTxt );
|
||||
match = RX::Mdx::srcRe.match( linkTxt );
|
||||
if( match.hasMatch() )
|
||||
{
|
||||
QString newText;
|
||||
|
@ -1104,7 +1063,7 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
|||
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
||||
}
|
||||
else
|
||||
newLink = linkTxt.replace( mdxRx.srcRe2,
|
||||
newLink = linkTxt.replace( RX::Mdx::srcRe2,
|
||||
"\\1\"bres://" + id + "/\\2\"" );
|
||||
}
|
||||
}
|
||||
|
@ -1409,7 +1368,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f
|
|||
if ( !parser.open( i->c_str() ) )
|
||||
continue;
|
||||
|
||||
string title = string( parser.title().toUtf8().constData() );
|
||||
string title = parser.title().toStdString();
|
||||
initializing.indexingDictionary( title );
|
||||
|
||||
for ( vector< string >::const_iterator mddIter = dictFiles.begin() + 1;
|
||||
|
@ -1440,7 +1399,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f
|
|||
|
||||
// then the encoding
|
||||
{
|
||||
string encoding = string( parser.encoding().toUtf8().constData() );
|
||||
string encoding = parser.encoding().toStdString();
|
||||
idx.write< uint32_t >( encoding.size() );
|
||||
idx.write( encoding.data(), encoding.size() );
|
||||
}
|
||||
|
@ -1457,7 +1416,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f
|
|||
|
||||
// Save dictionary description if there's one
|
||||
{
|
||||
string description = string( parser.description().toUtf8().constData() );
|
||||
string description = parser.description().toStdString();
|
||||
idxHeader.descriptionAddress = chunks.startNewBlock();
|
||||
chunks.addToBlock( description.c_str(), description.size() + 1 );
|
||||
idxHeader.descriptionSize = description.size() + 1;
|
||||
|
@ -1491,7 +1450,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f
|
|||
mddIndices.push_back( mddIndexedWords );
|
||||
// Save filename for .mdd files only
|
||||
QFileInfo fi( mddParser->filename() );
|
||||
mddFileNames.push_back( string( fi.fileName().toUtf8().constData() ) );
|
||||
mddFileNames.push_back( fi.fileName().toStdString() );
|
||||
mddParsers.pop_front();
|
||||
}
|
||||
|
||||
|
@ -1514,8 +1473,8 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f
|
|||
for ( MdictParser::StyleSheets::const_iterator iter = styleSheets.begin();
|
||||
iter != styleSheets.end(); ++iter )
|
||||
{
|
||||
string styleBegin( iter->second.first.toUtf8().constData() );
|
||||
string styleEnd( iter->second.second.toUtf8().constData() );
|
||||
string styleBegin(iter->second.first.toStdString());
|
||||
string styleEnd( iter->second.second.toStdString() );
|
||||
|
||||
// key
|
||||
idx.write<qint32>( iter->first );
|
||||
|
|
12
mediawiki.cc
12
mediawiki.cc
|
@ -47,16 +47,16 @@ public:
|
|||
langId = LangCoder::code2toInt( url.mid( n - 2, 2 ).toLatin1().data() );
|
||||
}
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return name; }
|
||||
|
||||
virtual map< Property, string > getProperties() throw()
|
||||
virtual map< Property, string > getProperties() noexcept
|
||||
{ return map< Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual sptr< WordSearchRequest > prefixMatch( wstring const &,
|
||||
|
@ -73,11 +73,11 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
};
|
||||
|
||||
void MediaWikiDictionary::loadIcon() throw()
|
||||
void MediaWikiDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
6
mutex.hh
6
mutex.hh
|
@ -4,16 +4,16 @@
|
|||
#ifndef __MUTEX_HH_INCLUDED__
|
||||
#define __MUTEX_HH_INCLUDED__
|
||||
|
||||
#include <QRecursiveMutex>
|
||||
#include <QMutex>
|
||||
|
||||
/// This provides a mutex class. As you can see, it's just a Qt one, but it
|
||||
/// does provide the Lock class which doesn't seem to exist in Qt, and it does
|
||||
/// provide some abstraction for dictionaries in case they are to be ported
|
||||
/// away from Qt.
|
||||
class Mutex : public QRecursiveMutex
|
||||
class Mutex : public QMutex
|
||||
{
|
||||
public:
|
||||
Mutex() : QRecursiveMutex()
|
||||
Mutex() : QMutex()
|
||||
{}
|
||||
~Mutex()
|
||||
{}
|
||||
|
|
|
@ -323,6 +323,13 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
|
|||
ui.customSettingsGroup->setEnabled( p.proxyServer.enabled );
|
||||
}
|
||||
|
||||
//anki connect
|
||||
ui.useAnkiConnect->setChecked( p.ankiConnectServer.enabled );
|
||||
ui.ankiHost->setText( p.ankiConnectServer.host );
|
||||
ui.ankiPort->setValue( p.ankiConnectServer.port );
|
||||
ui.ankiModel->setText( p.ankiConnectServer.model );
|
||||
ui.ankiDeck->setText(p.ankiConnectServer.deck);
|
||||
|
||||
connect( ui.customProxy, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( customProxyToggled( bool ) ) );
|
||||
|
||||
|
@ -466,6 +473,13 @@ Config::Preferences Preferences::getPreferences()
|
|||
p.proxyServer.user = ui.proxyUser->text();
|
||||
p.proxyServer.password = ui.proxyPassword->text();
|
||||
|
||||
//anki connect
|
||||
p.ankiConnectServer.enabled = ui.useAnkiConnect->isChecked();
|
||||
p.ankiConnectServer.host = ui.ankiHost->text();
|
||||
p.ankiConnectServer.port = (unsigned)ui.ankiPort->value();
|
||||
p.ankiConnectServer.deck = ui.ankiDeck->text();
|
||||
p.ankiConnectServer.model = ui.ankiModel->text();
|
||||
|
||||
p.checkForNewReleases = ui.checkForNewReleases->isChecked();
|
||||
p.disallowContentFromOtherSites = ui.disallowContentFromOtherSites->isChecked();
|
||||
p.enableWebPlugins = ui.enableWebPlugins->isChecked();
|
||||
|
|
134
preferences.ui
134
preferences.ui
|
@ -993,6 +993,9 @@ for all program's network requests.</string>
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="customSettingsGroup">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Custom settings</string>
|
||||
</property>
|
||||
|
@ -1011,6 +1014,9 @@ for all program's network requests.</string>
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Host:</string>
|
||||
</property>
|
||||
|
@ -1073,20 +1079,110 @@ for all program's network requests.</string>
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_14">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<widget class="QGroupBox" name="useAnkiConnect">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
<property name="title">
|
||||
<string>Anki Connect</string>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</spacer>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_21">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Host:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>http://</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="ankiHost"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="ankiPort">
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8080</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_16">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_22">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Deck:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="ankiDeck"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>Model:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="ankiModel"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_17">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="disallowContentFromOtherSites">
|
||||
|
@ -1176,22 +1272,6 @@ clears its network cache from disk during exit.</string>
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkForNewReleases">
|
||||
<property name="toolTip">
|
||||
|
|
12
programs.cc
12
programs.cc
|
@ -30,16 +30,16 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return prg.name.toUtf8().data(); }
|
||||
|
||||
virtual map< Property, string > getProperties() throw()
|
||||
virtual map< Property, string > getProperties() noexcept
|
||||
{ return map< Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual sptr< WordSearchRequest > prefixMatch( wstring const & word,
|
||||
|
@ -53,7 +53,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
};
|
||||
|
||||
sptr< WordSearchRequest > ProgramsDictionary::prefixMatch( wstring const & word,
|
||||
|
@ -118,7 +118,7 @@ sptr< Dictionary::DataRequest > ProgramsDictionary::getArticle(
|
|||
}
|
||||
}
|
||||
|
||||
void ProgramsDictionary::loadIcon() throw()
|
||||
void ProgramsDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
|
@ -6,6 +6,11 @@ $(function() {
|
|||
if ('string' != typeof(link)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(link.indexOf("javascript:")>=0){
|
||||
return;
|
||||
}
|
||||
|
||||
if(link.indexOf(":")>=0){
|
||||
emitClickedEvent(link);
|
||||
return false;
|
||||
|
|
12
sdict.cc
12
sdict.cc
|
@ -143,16 +143,16 @@ class SdictDictionary: public BtreeIndexing::BtreeDictionary
|
|||
|
||||
~SdictDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -187,7 +187,7 @@ class SdictDictionary: public BtreeIndexing::BtreeDictionary
|
|||
}
|
||||
protected:
|
||||
|
||||
void loadIcon() throw();
|
||||
void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -240,7 +240,7 @@ SdictDictionary::~SdictDictionary()
|
|||
df.close();
|
||||
}
|
||||
|
||||
void SdictDictionary::loadIcon() throw()
|
||||
void SdictDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
18
slob.cc
18
slob.cc
|
@ -587,16 +587,16 @@ class SlobDictionary: public BtreeIndexing::BtreeDictionary
|
|||
|
||||
~SlobDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -643,7 +643,7 @@ class SlobDictionary: public BtreeIndexing::BtreeDictionary
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -694,12 +694,12 @@ SlobDictionary::SlobDictionary( string const & id,
|
|||
|
||||
// Read dictionary name
|
||||
|
||||
dictionaryName = string( sf.getDictionaryName().toUtf8().constData() );
|
||||
dictionaryName = sf.getDictionaryName().toStdString();
|
||||
if( dictionaryName.empty() )
|
||||
{
|
||||
QString name = QDir::fromNativeSeparators( FsEncoding::decode( dictionaryFiles[ 0 ].c_str() ) );
|
||||
int n = name.lastIndexOf( '/' );
|
||||
dictionaryName = string( name.mid( n + 1 ).toUtf8().constData() );
|
||||
dictionaryName = name.mid( n + 1 ).toStdString();
|
||||
}
|
||||
|
||||
// Full-text search parameters
|
||||
|
@ -746,7 +746,7 @@ void SlobDictionary::removeDirectory( QString const & directory )
|
|||
dir.rmdir( directory );
|
||||
}
|
||||
|
||||
void SlobDictionary::loadIcon() throw()
|
||||
void SlobDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
@ -799,7 +799,7 @@ void SlobDictionary::loadArticle( quint32 address,
|
|||
articleText = convert( articleText, entry );
|
||||
}
|
||||
else
|
||||
articleText = string( QObject::tr( "Article decoding error" ).toUtf8().constData() );
|
||||
articleText = QObject::tr( "Article decoding error" ).toStdString();
|
||||
|
||||
// See Issue #271: A mechanism to clean-up invalid HTML cards.
|
||||
string cleaner = "</font>""</font>""</font>""</font>""</font>""</font>"
|
||||
|
|
12
sounddir.cc
12
sounddir.cc
|
@ -79,16 +79,16 @@ public:
|
|||
vector< string > const & dictionaryFiles,
|
||||
QString const & iconFilename_ );
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return name; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.soundsCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return getArticleCount(); }
|
||||
|
||||
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
|
||||
|
@ -102,7 +102,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
};
|
||||
|
||||
SoundDirDictionary::SoundDirDictionary( string const & id,
|
||||
|
@ -289,7 +289,7 @@ sptr< Dictionary::DataRequest > SoundDirDictionary::getArticle( wstring const &
|
|||
return ret;
|
||||
}
|
||||
|
||||
void SoundDirDictionary::loadIcon() throw()
|
||||
void SoundDirDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
12
stardict.cc
12
stardict.cc
|
@ -155,16 +155,16 @@ public:
|
|||
|
||||
~StardictDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return bookName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount + idxHeader.synWordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -207,7 +207,7 @@ public:
|
|||
}
|
||||
protected:
|
||||
|
||||
void loadIcon() throw();
|
||||
void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -292,7 +292,7 @@ StardictDictionary::~StardictDictionary()
|
|||
dict_data_close( dz );
|
||||
}
|
||||
|
||||
void StardictDictionary::loadIcon() throw()
|
||||
void StardictDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
|
@ -22,16 +22,16 @@ BaseTransliterationDictionary::BaseTransliterationDictionary( string const & id,
|
|||
dictionaryIconLoaded = true;
|
||||
}
|
||||
|
||||
string BaseTransliterationDictionary::getName() throw()
|
||||
string BaseTransliterationDictionary::getName() noexcept
|
||||
{ return name; }
|
||||
|
||||
map< Dictionary::Property, string > BaseTransliterationDictionary::getProperties() throw()
|
||||
map< Dictionary::Property, string > BaseTransliterationDictionary::getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
unsigned long BaseTransliterationDictionary::getArticleCount() throw()
|
||||
unsigned long BaseTransliterationDictionary::getArticleCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
unsigned long BaseTransliterationDictionary::getWordCount() throw()
|
||||
unsigned long BaseTransliterationDictionary::getWordCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
sptr< Dictionary::WordSearchRequest > BaseTransliterationDictionary::prefixMatch( wstring const &,
|
||||
|
@ -83,7 +83,7 @@ TransliterationDictionary::TransliterationDictionary( string const & id,
|
|||
}
|
||||
|
||||
vector< wstring > TransliterationDictionary::getAlternateWritings( wstring const & str )
|
||||
throw()
|
||||
noexcept
|
||||
{
|
||||
vector< wstring > results;
|
||||
|
||||
|
|
|
@ -28,16 +28,16 @@ public:
|
|||
BaseTransliterationDictionary( string const & id, string const & name,
|
||||
QIcon icon, bool caseSensitive = true );
|
||||
|
||||
virtual string getName() throw();
|
||||
virtual string getName() noexcept;
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw();
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept;
|
||||
|
||||
virtual unsigned long getArticleCount() throw();
|
||||
virtual unsigned long getArticleCount() noexcept;
|
||||
|
||||
virtual unsigned long getWordCount() throw();
|
||||
virtual unsigned long getWordCount() noexcept;
|
||||
|
||||
virtual vector< wstring > getAlternateWritings( wstring const & )
|
||||
throw() = 0;
|
||||
noexcept = 0;
|
||||
|
||||
virtual sptr< Dictionary::WordSearchRequest > findHeadwordsForSynonym( wstring const & )
|
||||
;
|
||||
|
@ -85,7 +85,7 @@ public:
|
|||
bool caseSensitive = true );
|
||||
|
||||
virtual vector< wstring > getAlternateWritings( wstring const & )
|
||||
throw();
|
||||
noexcept;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
334
uiauto.hh
334
uiauto.hh
|
@ -1,334 +0,0 @@
|
|||
#ifndef __UIAUTO_HH_INCLUDED__
|
||||
#define __UIAUTO_HH_INCLUDED__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <oleacc.h>
|
||||
|
||||
EXTERN_C const IID IID_IUIAutomation;
|
||||
EXTERN_C const IID CLSID_CUIAutomation;
|
||||
EXTERN_C const IID IID_IUIAutomationElement;
|
||||
EXTERN_C const IID IID_IUIAutomationTextPattern;
|
||||
EXTERN_C const IID IID_IUIAutomationTextRange;
|
||||
EXTERN_C const IID IID_IUIAutomationTreeWalker;
|
||||
|
||||
typedef interface IUIAutomationElement IUIAutomationElement;
|
||||
typedef interface IUIAutomationElementArray IUIAutomationElementArray;
|
||||
typedef interface IUIAutomationTextPattern IUIAutomationTextPattern;
|
||||
typedef interface IUIAutomationTextRange IUIAutomationTextRange;
|
||||
typedef interface IUIAutomationTextRangeArray IUIAutomationTextRangeArray;
|
||||
typedef interface IUIAutomationCacheRequest IUIAutomationCacheRequest;
|
||||
typedef interface IUIAutomationTreeWalker IUIAutomationTreeWalker;
|
||||
typedef interface IUIAutomationCondition IUIAutomationCondition;
|
||||
typedef interface IUIAutomationEventHandler IUIAutomationEventHandler;
|
||||
typedef interface IUIAutomationPropertyChangedEventHandler IUIAutomationPropertyChangedEventHandler;
|
||||
typedef interface IUIAutomationStructureChangedEventHandler IUIAutomationStructureChangedEventHandler;
|
||||
typedef interface IUIAutomationFocusChangedEventHandler IUIAutomationFocusChangedEventHandler;
|
||||
typedef interface IUIAutomationProxyFactory IUIAutomationProxyFactory;
|
||||
typedef interface IUIAutomationProxyFactoryEntry IUIAutomationProxyFactoryEntry;
|
||||
typedef interface IUIAutomationProxyFactoryMapping IUIAutomationProxyFactoryMapping;
|
||||
|
||||
typedef void *UIA_HWND;
|
||||
typedef int PROPERTYID;
|
||||
typedef int EVENTID;
|
||||
typedef int PATTERNID;
|
||||
typedef int CONTROLTYPEID;
|
||||
typedef int TEXTATTRIBUTEID;
|
||||
|
||||
enum TreeScope
|
||||
{
|
||||
TreeScope_Element = 0x1,
|
||||
TreeScope_Children = 0x2,
|
||||
TreeScope_Descendants = 0x4,
|
||||
TreeScope_Parent = 0x8,
|
||||
TreeScope_Ancestors = 0x10,
|
||||
TreeScope_Subtree = ( ( TreeScope_Element | TreeScope_Children ) | TreeScope_Descendants )
|
||||
};
|
||||
|
||||
enum PropertyConditionFlags
|
||||
{
|
||||
PropertyConditionFlags_None = 0,
|
||||
PropertyConditionFlags_IgnoreCase = 0x1
|
||||
};
|
||||
|
||||
enum OrientationType
|
||||
{
|
||||
OrientationType_None = 0,
|
||||
OrientationType_Horizontal = 1,
|
||||
OrientationType_Vertical = 2
|
||||
};
|
||||
|
||||
enum SupportedTextSelection
|
||||
{
|
||||
SupportedTextSelection_None = 0,
|
||||
SupportedTextSelection_Single = 1,
|
||||
SupportedTextSelection_Multiple = 2
|
||||
};
|
||||
|
||||
enum TextPatternRangeEndpoint
|
||||
{
|
||||
TextPatternRangeEndpoint_Start = 0,
|
||||
TextPatternRangeEndpoint_End = 1
|
||||
};
|
||||
|
||||
enum TextUnit
|
||||
{
|
||||
TextUnit_Character = 0,
|
||||
TextUnit_Format = 1,
|
||||
TextUnit_Word = 2,
|
||||
TextUnit_Line = 3,
|
||||
TextUnit_Paragraph = 4,
|
||||
TextUnit_Page = 5,
|
||||
TextUnit_Document = 6
|
||||
};
|
||||
|
||||
enum ProviderOptions
|
||||
{
|
||||
ProviderOptions_ClientSideProvider = 0x1,
|
||||
ProviderOptions_ServerSideProvider = 0x2,
|
||||
ProviderOptions_NonClientAreaProvider = 0x4,
|
||||
ProviderOptions_OverrideProvider = 0x8,
|
||||
ProviderOptions_ProviderOwnsSetFocus = 0x10,
|
||||
ProviderOptions_UseComThreading = 0x20
|
||||
} ;
|
||||
|
||||
/* UIA_PatternIds */
|
||||
const long UIA_InvokePatternId = 10000;
|
||||
const long UIA_SelectionPatternId = 10001;
|
||||
const long UIA_ValuePatternId = 10002;
|
||||
const long UIA_RangeValuePatternId = 10003;
|
||||
const long UIA_ScrollPatternId = 10004;
|
||||
const long UIA_ExpandCollapsePatternId = 10005;
|
||||
const long UIA_GridPatternId = 10006;
|
||||
const long UIA_GridItemPatternId = 10007;
|
||||
const long UIA_MultipleViewPatternId = 10008;
|
||||
const long UIA_WindowPatternId = 10009;
|
||||
const long UIA_SelectionItemPatternId = 10010;
|
||||
const long UIA_DockPatternId = 10011;
|
||||
const long UIA_TablePatternId = 10012;
|
||||
const long UIA_TableItemPatternId = 10013;
|
||||
const long UIA_TextPatternId = 10014;
|
||||
const long UIA_TogglePatternId = 10015;
|
||||
const long UIA_TransformPatternId = 10016;
|
||||
const long UIA_ScrollItemPatternId = 10017;
|
||||
const long UIA_LegacyIAccessiblePatternId = 10018;
|
||||
const long UIA_ItemContainerPatternId = 10019;
|
||||
const long UIA_VirtualizedItemPatternId = 10020;
|
||||
const long UIA_SynchronizedInputPatternId = 10021;
|
||||
|
||||
#ifdef INTERFACE
|
||||
#undef INTERFACE
|
||||
#endif
|
||||
|
||||
#define INTERFACE IUIAutomation
|
||||
DECLARE_INTERFACE_(IUIAutomation, IUnknown)
|
||||
{
|
||||
STDMETHOD(CompareElements)(THIS_ IUIAutomationElement *, IUIAutomationElement *, BOOL *) PURE;
|
||||
STDMETHOD(CompareRuntimeIds)(THIS_ SAFEARRAY *, SAFEARRAY *, BOOL *) PURE;
|
||||
STDMETHOD(GetRootElement)(THIS_ IUIAutomationElement **) PURE;
|
||||
STDMETHOD(ElementFromHandle)(THIS_ UIA_HWND, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(ElementFromPoint)(THIS_ POINT, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetFocusedElement)(THIS_ IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetRootElementBuildCache)(THIS_ IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(ElementFromHandleBuildCache)(THIS_ UIA_HWND, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(ElementFromPointBuildCache)(THIS_ POINT, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetFocusedElementBuildCache)(THIS_ IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(CreateTreeWalker)(THIS_ IUIAutomationCondition *, IUIAutomationTreeWalker **) PURE;
|
||||
STDMETHOD(get_ControlViewWalker)(THIS_ IUIAutomationTreeWalker **) PURE;
|
||||
STDMETHOD(get_ContentViewWalker)(THIS_ IUIAutomationTreeWalker **) PURE;
|
||||
STDMETHOD(get_RawViewWalker)(THIS_ IUIAutomationTreeWalker **) PURE;
|
||||
STDMETHOD(get_RawViewCondition)(THIS_ IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(get_ControlViewCondition)(THIS_ IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(get_ContentViewCondition)(THIS_ IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateCacheRequest)(THIS_ IUIAutomationCacheRequest **) PURE;
|
||||
STDMETHOD(CreateTrueCondition)(THIS_ IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateFalseCondition)(THIS_ IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreatePropertyCondition)(THIS_ PROPERTYID, VARIANT, IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreatePropertyConditionEx)(THIS_ PROPERTYID, VARIANT, enum PropertyConditionFlags, IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateAndCondition)(THIS_ IUIAutomationCondition *, IUIAutomationCondition *, IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateAndConditionFromArray)(THIS_ SAFEARRAY *, IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateAndConditionFromNativeArray)(THIS_ IUIAutomationCondition **, int , IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateOrCondition)(THIS_ IUIAutomationCondition *, IUIAutomationCondition *, IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateOrConditionFromArray)(THIS_ SAFEARRAY *, IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateOrConditionFromNativeArray)(THIS_ IUIAutomationCondition **, int , IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(CreateNotCondition)(THIS_ IUIAutomationCondition *, IUIAutomationCondition **) PURE;
|
||||
STDMETHOD(AddAutomationEventHandler)(THIS_ EVENTID, IUIAutomationElement *, enum TreeScope, IUIAutomationCacheRequest *, IUIAutomationEventHandler *) PURE;
|
||||
STDMETHOD(RemoveAutomationEventHandler)(THIS_ EVENTID, IUIAutomationElement *, IUIAutomationEventHandler *) PURE;
|
||||
STDMETHOD(AddPropertyChangedEventHandlerNativeArray)(THIS_ IUIAutomationElement *, enum TreeScope, IUIAutomationCacheRequest *,
|
||||
IUIAutomationPropertyChangedEventHandler *, PROPERTYID *, int) PURE;
|
||||
STDMETHOD(AddPropertyChangedEventHandler)(THIS_ IUIAutomationElement *, enum TreeScope, EVENTID, IUIAutomationCacheRequest *,
|
||||
IUIAutomationPropertyChangedEventHandler *, SAFEARRAY *) PURE;
|
||||
STDMETHOD(RemovePropertyChangedEventHandler)(THIS_ IUIAutomationElement *, IUIAutomationPropertyChangedEventHandler *) PURE;
|
||||
STDMETHOD(AddStructureChangedEventHandler)(THIS_ IUIAutomationElement *, enum TreeScope, IUIAutomationCacheRequest *, IUIAutomationStructureChangedEventHandler *) PURE;
|
||||
STDMETHOD(RemoveStructureChangedEventHandler)(THIS_ IUIAutomationElement *, IUIAutomationStructureChangedEventHandler *) PURE;
|
||||
STDMETHOD(AddFocusChangedEventHandler)(THIS_ IUIAutomationCacheRequest *, IUIAutomationFocusChangedEventHandler *) PURE;
|
||||
STDMETHOD(RemoveFocusChangedEventHandler)(THIS_ IUIAutomationFocusChangedEventHandler *) PURE;
|
||||
STDMETHOD(RemoveAllEventHandlers)(THIS) PURE;
|
||||
STDMETHOD(IntNativeArrayToSafeArray)(THIS_ int *, int, SAFEARRAY **) PURE;
|
||||
STDMETHOD(IntSafeArrayToNativeArray)(THIS_ SAFEARRAY *, int **, int *) PURE;
|
||||
STDMETHOD(RectToVariant)(THIS_ RECT, VARIANT *) PURE;
|
||||
STDMETHOD(VariantToRect)(THIS_ VARIANT, RECT *) PURE;
|
||||
STDMETHOD(SafeArrayToRectNativeArray)(THIS_ SAFEARRAY *, RECT **, int *) PURE;
|
||||
STDMETHOD(CreateProxyFactoryEntry)(THIS_ IUIAutomationProxyFactory *, IUIAutomationProxyFactoryEntry **) PURE;
|
||||
STDMETHOD(get_ProxyFactoryMapping)(THIS_ IUIAutomationProxyFactoryMapping **) PURE;
|
||||
STDMETHOD(GetPropertyProgrammaticName)(THIS_ PROPERTYID, BSTR *) PURE;
|
||||
STDMETHOD(GetPatternProgrammaticName)(THIS_ PATTERNID, BSTR *) PURE;
|
||||
STDMETHOD(PollForPotentialSupportedPatterns)(THIS_ IUIAutomationElement *, SAFEARRAY **, SAFEARRAY **) PURE;
|
||||
STDMETHOD(PollForPotentialSupportedProperties)(THIS_ IUIAutomationElement *, SAFEARRAY **, SAFEARRAY **) PURE;
|
||||
STDMETHOD(CheckNotSupported)(THIS_ VARIANT, BOOL *) PURE;
|
||||
STDMETHOD(get_ReservedNotSupportedValue)(THIS_ IUnknown **) PURE;
|
||||
STDMETHOD(get_ReservedMixedAttributeValue)(THIS_ IUnknown **) PURE;
|
||||
STDMETHOD(ElementFromIAccessible)(THIS_ IAccessible *, int, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(ElementFromIAccessibleBuildCache)(THIS_ IAccessible *, int, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
#define INTERFACE IUIAutomationElement
|
||||
DECLARE_INTERFACE_(IUIAutomationElement, IUnknown)
|
||||
{
|
||||
STDMETHOD(SetFocus)(THIS) PURE;
|
||||
STDMETHOD(GetRuntimeId)(THIS_ SAFEARRAY **) PURE;
|
||||
STDMETHOD(FindFirst)(THIS_ enum TreeScope, IUIAutomationCondition *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(FindAll)(THIS_ enum TreeScope, IUIAutomationCondition *, IUIAutomationElementArray **) PURE;
|
||||
STDMETHOD(FindFirstBuildCache)(THIS_ enum TreeScope, IUIAutomationCondition *, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(FindAllBuildCache)(THIS_ enum TreeScope, IUIAutomationCondition *, IUIAutomationCacheRequest *, IUIAutomationElementArray **) PURE;
|
||||
STDMETHOD(BuildUpdatedCache)(THIS_ IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetCurrentPropertyValue)(THIS_ PROPERTYID, VARIANT *) PURE;
|
||||
STDMETHOD(GetCurrentPropertyValueEx)(THIS_ PROPERTYID, BOOL, VARIANT *) PURE;
|
||||
STDMETHOD(GetCachedPropertyValue)(THIS_ PROPERTYID, VARIANT *) PURE;
|
||||
STDMETHOD(GetCachedPropertyValueEx)(THIS_ PROPERTYID, BOOL, VARIANT *) PURE;
|
||||
STDMETHOD(GetCurrentPatternAs)(THIS_ PATTERNID, REFIID, void **) PURE;
|
||||
STDMETHOD(GetCachedPatternAs)(THIS_ PATTERNID, REFIID, void **) PURE;
|
||||
STDMETHOD(GetCurrentPattern)(THIS_ PATTERNID, IUnknown **) PURE;
|
||||
STDMETHOD(GetCachedPattern)(THIS_ PATTERNID, IUnknown **) PURE;
|
||||
STDMETHOD(GetCachedParent)(THIS_ IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetCachedChildren)(THIS_ IUIAutomationElement **) PURE;
|
||||
STDMETHOD(get_CurrentProcessId)(THIS_ int *) PURE;
|
||||
STDMETHOD(get_CurrentControlType)(THIS_ CONTROLTYPEID *) PURE;
|
||||
STDMETHOD(get_CurrentLocalizedControlType)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentName)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentAcceleratorKey)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentAccessKey)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentHasKeyboardFocus)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentIsKeyboardFocusable)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentIsEnabled)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentAutomationId)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentClassName)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentHelpText)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentCulture)(THIS_ int *) PURE;
|
||||
STDMETHOD(get_CurrentIsControlElement)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentIsContentElement)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentIsPassword)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentNativeWindowHandle)(THIS_ UIA_HWND *) PURE;
|
||||
STDMETHOD(get_CurrentItemType)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentIsOffscreen)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentOrientation)(THIS_ enum OrientationType *) PURE;
|
||||
STDMETHOD(get_CurrentFrameworkId)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentIsRequiredForForm)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentItemStatus)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentBoundingRectangle)(THIS_ RECT *) PURE;
|
||||
STDMETHOD(get_CurrentLabeledBy)(THIS_ IUIAutomationElement **) PURE;
|
||||
STDMETHOD(get_CurrentAriaRole)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentAriaProperties)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CurrentIsDataValidForForm)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CurrentControllerFor)(THIS_ IUIAutomationElementArray **) PURE;
|
||||
STDMETHOD(get_CurrentDescribedBy)(THIS_ IUIAutomationElementArray **) PURE;
|
||||
STDMETHOD(get_CurrentFlowsTo)(THIS_ IUIAutomationElementArray **) PURE;
|
||||
STDMETHOD(get_CurrentProviderDescription)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedProcessId)(THIS_ int *) PURE;
|
||||
STDMETHOD(get_CachedControlType)(THIS_ CONTROLTYPEID *) PURE;
|
||||
STDMETHOD(get_CachedLocalizedControlType)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedName)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedAcceleratorKey)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedAccessKey)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedHasKeyboardFocus)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedIsKeyboardFocusable)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedIsEnabled)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedAutomationId)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedClassName)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedHelpText)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedCulture)(THIS_ int *) PURE;
|
||||
STDMETHOD(get_CachedIsControlElement)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedIsContentElement)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedIsPassword)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedNativeWindowHandle)(THIS_ UIA_HWND *) PURE;
|
||||
STDMETHOD(get_CachedItemType)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedIsOffscreen)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedOrientation)(THIS_ enum OrientationType *) PURE;
|
||||
STDMETHOD(get_CachedFrameworkId)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedIsRequiredForForm)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedItemStatus)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedBoundingRectangle)(THIS_ RECT *) PURE;
|
||||
STDMETHOD(get_CachedLabeledBy)(THIS_ IUIAutomationElement **) PURE;
|
||||
STDMETHOD(get_CachedAriaRole)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedAriaProperties)(THIS_ BSTR *) PURE;
|
||||
STDMETHOD(get_CachedIsDataValidForForm)(THIS_ BOOL *) PURE;
|
||||
STDMETHOD(get_CachedControllerFor)(THIS_ IUIAutomationElementArray **) PURE;
|
||||
STDMETHOD(get_CachedDescribedBy)(THIS_ IUIAutomationElementArray **) PURE;
|
||||
STDMETHOD(get_CachedFlowsTo)(THIS_ IUIAutomationElementArray **) PURE;
|
||||
STDMETHOD(get_CachedProviderDescription)(THIS_ BSTR *) PURE;
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
#define INTERFACE IUIAutomationTextPattern
|
||||
DECLARE_INTERFACE_(IUIAutomationTextPattern, IUnknown)
|
||||
{
|
||||
STDMETHOD(RangeFromPoint)(THIS_ POINT, IUIAutomationTextRange **) PURE;
|
||||
STDMETHOD(RangeFromChild)(THIS_ IUIAutomationElement *, IUIAutomationTextRange **) PURE;
|
||||
STDMETHOD(GetSelection)(THIS_ IUIAutomationTextRangeArray **) PURE;
|
||||
STDMETHOD(GetVisibleRanges)(THIS_ IUIAutomationTextRangeArray **) PURE;
|
||||
STDMETHOD(get_DocumentRange)(THIS_ IUIAutomationTextRange **) PURE;
|
||||
STDMETHOD(get_SupportedTextSelection)(THIS_ enum SupportedTextSelection *) PURE;
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
#define INTERFACE IUIAutomationTreeWalker
|
||||
DECLARE_INTERFACE_(IUIAutomationTreeWalker, IUnknown)
|
||||
{
|
||||
STDMETHOD(GetParentElement)(THIS_ IUIAutomationElement *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetFirstChildElement)(THIS_ IUIAutomationElement *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetLastChildElement)(THIS_ IUIAutomationElement *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetNextSiblingElement)(THIS_ IUIAutomationElement *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetPreviousSiblingElement)(THIS_ IUIAutomationElement *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(NormalizeElement)(THIS_ IUIAutomationElement *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetParentElementBuildCache)(THIS_ IUIAutomationElement *, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetFirstChildElementBuildCache)(THIS_ IUIAutomationElement *, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetLastChildElementBuildCache)(THIS_ IUIAutomationElement *, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetNextSiblingElementBuildCache)(THIS_ IUIAutomationElement *, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetPreviousSiblingElementBuildCache)(THIS_ IUIAutomationElement *, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(NormalizeElementBuildCache)(THIS_ IUIAutomationElement *, IUIAutomationCacheRequest *, IUIAutomationElement **) PURE;
|
||||
STDMETHOD(get_Condition)(THIS_ IUIAutomationCondition **) PURE;
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
#define INTERFACE IUIAutomationTextRange
|
||||
DECLARE_INTERFACE_(IUIAutomationTextRange, IUnknown)
|
||||
{
|
||||
STDMETHOD(Clone)(THIS_ IUIAutomationTextRange **) PURE;
|
||||
STDMETHOD(Compare)(THIS_ IUIAutomationTextRange *, BOOL *) PURE;
|
||||
STDMETHOD(CompareEndpoints)(THIS_ enum TextPatternRangeEndpoint, IUIAutomationTextRange *, enum TextPatternRangeEndpoint, int *) PURE;
|
||||
STDMETHOD(ExpandToEnclosingUnit)(THIS_ enum TextUnit) PURE;
|
||||
STDMETHOD(FindAttribute)(THIS_ TEXTATTRIBUTEID, VARIANT, BOOL, IUIAutomationTextRange **) PURE;
|
||||
STDMETHOD(FindText)(THIS_ BSTR, BOOL, BOOL, IUIAutomationTextRange **) PURE;
|
||||
STDMETHOD(GetAttributeValue)(THIS_ TEXTATTRIBUTEID, VARIANT *) PURE;
|
||||
STDMETHOD(GetBoundingRectangles)(THIS_ SAFEARRAY **) PURE;
|
||||
STDMETHOD(GetEnclosingElement)(THIS_ IUIAutomationElement **) PURE;
|
||||
STDMETHOD(GetText)(THIS_ int, BSTR *) PURE;
|
||||
STDMETHOD(Move)(THIS_ enum TextUnit, int, int *) PURE;
|
||||
STDMETHOD(MoveEndpointByUnit)(THIS_ enum TextPatternRangeEndpoint, enum TextUnit, int *) PURE;
|
||||
STDMETHOD(MoveEndpointByRange)(THIS_ enum TextPatternRangeEndpoint, IUIAutomationTextRange *, enum TextPatternRangeEndpoint) PURE;
|
||||
STDMETHOD(Select)(THIS) PURE;
|
||||
STDMETHOD(AddToSelection)(THIS) PURE;
|
||||
STDMETHOD(RemoveFromSelection)(THIS) PURE;
|
||||
STDMETHOD(ScrollIntoView)(THIS_ BOOL) PURE;
|
||||
STDMETHOD(GetChildren)(THIS_ IUIAutomationElementArray **) PURE;
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // UIAUTO_HH
|
2
utf8.cc
2
utf8.cc
|
@ -132,7 +132,7 @@ long decode( char const * in_, size_t inSize, wchar * out_ )
|
|||
return out - out_;
|
||||
}
|
||||
|
||||
string encode( wstring const & in ) throw()
|
||||
string encode( wstring const & in ) noexcept
|
||||
{
|
||||
if( in.size() == 0 )
|
||||
return string();
|
||||
|
|
2
utf8.hh
2
utf8.hh
|
@ -44,7 +44,7 @@ size_t encode( wchar const * in, size_t inSize, char * out );
|
|||
long decode( char const * in, size_t inSize, wchar * out );
|
||||
|
||||
/// Versions for non time-critical code.
|
||||
string encode( wstring const & ) throw();
|
||||
string encode( wstring const & ) noexcept;
|
||||
wstring decode( string const & ) ;
|
||||
|
||||
/// Since the standard isspace() is locale-specific, we need something
|
||||
|
|
113
utils.hh
113
utils.hh
|
@ -9,6 +9,8 @@
|
|||
#include <QKeyEvent>
|
||||
#include <QUrl>
|
||||
#include <QUrlQuery>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
|
@ -26,6 +28,39 @@ inline QString rstrip(const QString &str) {
|
|||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* remove punctuation , space, symbol
|
||||
*
|
||||
*
|
||||
* " abc, '" should be "abc"
|
||||
*/
|
||||
inline QString trimNonChar( const QString & str )
|
||||
{
|
||||
QString remain;
|
||||
int n = str.size() - 1;
|
||||
for( ; n >= 0; --n )
|
||||
{
|
||||
auto c = str.at( n );
|
||||
if( !c.isSpace() && !c.isSymbol() && !c.isNonCharacter() && !c.isPunct()&& !c.isNull() )
|
||||
{
|
||||
remain = str.left( n + 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
n = 0;
|
||||
for( ; n < remain.size(); n++ )
|
||||
{
|
||||
auto c = remain.at( n );
|
||||
if( !c.isSpace() && !c.isSymbol() && !c.isNonCharacter() && !c.isPunct() )
|
||||
{
|
||||
return remain.mid( n );
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* str="abc\r\n\u0000" should be returned as "abc"
|
||||
* @brief rstripnull
|
||||
|
@ -35,20 +70,14 @@ inline QString rstrip(const QString &str) {
|
|||
inline QString rstripnull(const QString &str) {
|
||||
int n = str.size() - 1;
|
||||
for (; n >= 0; --n) {
|
||||
if (!str.at(n).isSpace()&&!str.at(n).isNull()) {
|
||||
auto c = str.at(n);
|
||||
if (!c.isSpace()&&!c.isNull()) {
|
||||
return str.left(n + 1);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
inline QString unescapeHtml(const QString &str) {
|
||||
QTextDocument text;
|
||||
text.setHtml(str);
|
||||
return text.toPlainText();
|
||||
}
|
||||
|
||||
|
||||
inline bool isExternalLink(QUrl const &url) {
|
||||
return url.scheme() == "http" || url.scheme() == "https" || url.scheme() == "ftp" || url.scheme() == "mailto" ||
|
||||
url.scheme() == "file" || url.toString().startsWith( "//" );
|
||||
|
@ -77,6 +106,21 @@ inline bool ignoreKeyEvent(QKeyEvent *keyEvent) {
|
|||
return false;
|
||||
}
|
||||
|
||||
inline QString json2String( const QJsonObject & json )
|
||||
{
|
||||
return QString( QJsonDocument( json ).toJson( QJsonDocument::Compact ) );
|
||||
}
|
||||
|
||||
inline QStringList repeat( const QString str, const int times )
|
||||
{
|
||||
QStringList list;
|
||||
for( int i = 0; i < times; i++ )
|
||||
{
|
||||
list << str;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
namespace AtomicInt
|
||||
{
|
||||
|
||||
|
@ -89,6 +133,7 @@ inline int loadAcquire( QAtomicInt const & ref )
|
|||
|
||||
namespace Url
|
||||
{
|
||||
|
||||
// This wrapper is created due to behavior change of the setPath() method
|
||||
// See: https://bugreports.qt-project.org/browse/QTBUG-27728
|
||||
// https://codereview.qt-project.org/#change,38257
|
||||
|
@ -151,16 +196,15 @@ inline QString fragment( const QUrl & url )
|
|||
return url.fragment( QUrl::FullyDecoded );
|
||||
}
|
||||
|
||||
// extract query word from url
|
||||
inline QString getWordFromUrl( const QUrl & url )
|
||||
// get the query word of bword and gdlookup scheme.
|
||||
// if the scheme is gdlookup or scheme ,the first value of pair is true,otherwise is false;
|
||||
inline std::pair< bool, QString > getQueryWord( QUrl const & url )
|
||||
{
|
||||
QString word;
|
||||
if( url.scheme().compare( "bword" ) == 0 )
|
||||
{
|
||||
word = url.path();
|
||||
}
|
||||
else if( url.scheme() == "gdlookup" ) // Plain html links inherit gdlookup scheme
|
||||
bool validScheme = false;
|
||||
if( url.scheme().compare( "gdlookup" ) == 0 )
|
||||
{
|
||||
validScheme = true;
|
||||
if( hasQueryItem( url, "word" ) )
|
||||
{
|
||||
word = queryItemValue( url, "word" );
|
||||
|
@ -170,8 +214,31 @@ inline QString getWordFromUrl( const QUrl & url )
|
|||
word = url.path().mid( 1 );
|
||||
}
|
||||
}
|
||||
if( url.scheme().compare( "bword" ) == 0 || url.scheme().compare( "entry" ) == 0 )
|
||||
{
|
||||
validScheme = true;
|
||||
|
||||
return word;
|
||||
auto path = url.path();
|
||||
// url like this , bword:word or bword://localhost/word
|
||||
if( !path.isEmpty() )
|
||||
{
|
||||
//url,bword://localhost/word
|
||||
if( path.startsWith( "/" ) )
|
||||
word = path.mid( 1 );
|
||||
else
|
||||
word = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
// url looks like this, bword://word,or bword://localhost
|
||||
auto host = url.host();
|
||||
if( host != "localhost" )
|
||||
{
|
||||
word = host;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_pair( validScheme, word );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,13 +248,6 @@ namespace
|
|||
{
|
||||
/// Uses some heuristics to chop off the first domain name from the host name,
|
||||
/// but only if it's not too base. Returns the resulting host name.
|
||||
inline QString getHostBase( QUrl const & url )
|
||||
{
|
||||
QString host = url.host();
|
||||
|
||||
return getHostBase(host);
|
||||
}
|
||||
|
||||
inline QString getHostBase( QString const & host )
|
||||
{
|
||||
QStringList domains = host.split( '.' );
|
||||
|
@ -212,6 +272,13 @@ inline QString getHostBase( QString const & host )
|
|||
else
|
||||
return host;
|
||||
}
|
||||
|
||||
inline QString getHostBaseFromUrl( QUrl const & url )
|
||||
{
|
||||
QString host = url.host();
|
||||
|
||||
return getHostBase( host );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTILS_HH
|
||||
|
|
|
@ -44,16 +44,16 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return voiceEngine.name.toUtf8().data(); }
|
||||
|
||||
virtual map< Property, string > getProperties() throw()
|
||||
virtual map< Property, string > getProperties() noexcept
|
||||
{ return map< Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual sptr< WordSearchRequest > prefixMatch( wstring const & word,
|
||||
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
};
|
||||
|
||||
sptr< WordSearchRequest > VoiceEnginesDictionary::prefixMatch( wstring const & /*word*/,
|
||||
|
@ -110,7 +110,7 @@ sptr< Dictionary::DataRequest > VoiceEnginesDictionary::getArticle(
|
|||
return ret;
|
||||
}
|
||||
|
||||
void VoiceEnginesDictionary::loadIcon() throw()
|
||||
void VoiceEnginesDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
12
website.cc
12
website.cc
|
@ -53,16 +53,16 @@ public:
|
|||
dictionaryDescription = temp;
|
||||
}
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return name; }
|
||||
|
||||
virtual map< Property, string > getProperties() throw()
|
||||
virtual map< Property, string > getProperties() noexcept
|
||||
{ return map< Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return 0; }
|
||||
|
||||
virtual sptr< WordSearchRequest > prefixMatch( wstring const & word,
|
||||
|
@ -79,7 +79,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
};
|
||||
|
||||
sptr< WordSearchRequest > WebSiteDictionary::prefixMatch( wstring const & /*word*/,
|
||||
|
@ -526,7 +526,7 @@ sptr< Dictionary::DataRequest > WebSiteDictionary::getResource( string const & n
|
|||
return new WebSiteResourceRequest( link, netMgr, this );
|
||||
}
|
||||
|
||||
void WebSiteDictionary::loadIcon() throw()
|
||||
void WebSiteDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
114
wordbyauto.cc
114
wordbyauto.cc
|
@ -1,114 +0,0 @@
|
|||
#include <windows.h>
|
||||
#include <servprov.h>
|
||||
#include "wordbyauto.hh"
|
||||
#include "uiauto.hh"
|
||||
|
||||
#include <cstdio>
|
||||
#include "gddebug.hh"
|
||||
|
||||
class GDAutomationClient {
|
||||
public:
|
||||
GDAutomationClient();
|
||||
~GDAutomationClient();
|
||||
bool getWordAtPoint( POINT pt );
|
||||
WCHAR *getText() { return buffer; }
|
||||
private:
|
||||
WCHAR buffer[256];
|
||||
IUIAutomation *pGDAutomation;
|
||||
IUIAutomationTreeWalker *pTree;
|
||||
};
|
||||
|
||||
GDAutomationClient gdAuto;
|
||||
|
||||
GDAutomationClient::GDAutomationClient()
|
||||
{
|
||||
HRESULT hr;
|
||||
CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
|
||||
hr = CoCreateInstance( CLSID_CUIAutomation , NULL, CLSCTX_INPROC_SERVER, IID_IUIAutomation, (void**)&pGDAutomation );
|
||||
if( hr != S_OK ) pGDAutomation = NULL;
|
||||
pTree = NULL;
|
||||
if( pGDAutomation != NULL )
|
||||
hr = pGDAutomation->get_RawViewWalker( &pTree );
|
||||
memset( buffer, 0, sizeof(buffer) );
|
||||
}
|
||||
|
||||
GDAutomationClient::~GDAutomationClient()
|
||||
{
|
||||
if( pTree != NULL ) pTree->Release();
|
||||
if( pGDAutomation != NULL ) pGDAutomation->Release();
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
bool GDAutomationClient::getWordAtPoint( POINT pt )
|
||||
{
|
||||
HRESULT hr;
|
||||
IUIAutomationTextPattern *pTextPattern;
|
||||
IUIAutomationTextRange *pTextRange;
|
||||
IUIAutomationElement *pElement, *pParent;
|
||||
BSTR bstr;
|
||||
RECT r = { 0, 0, 0, 0 };
|
||||
bool bGoUp;
|
||||
|
||||
GD_DPRINTF("\nEntering getWordAtPoint\n");
|
||||
|
||||
if( pGDAutomation == NULL ) return false;
|
||||
|
||||
buffer[0] = 0;
|
||||
pElement = NULL;
|
||||
hr = pGDAutomation->ElementFromPoint( pt, &pElement );
|
||||
GD_DPRINTF("ElementFromPoint return hr=%08lX, ptr=%p\n", hr, pElement);
|
||||
if( hr != S_OK || pElement == NULL )
|
||||
return false;
|
||||
|
||||
pTextPattern = NULL;
|
||||
bGoUp = false;
|
||||
while( pElement != NULL ) {
|
||||
hr = pElement->GetCurrentPatternAs( UIA_TextPatternId, IID_IUIAutomationTextPattern, (void**)&pTextPattern );
|
||||
if( hr == S_OK && pTextPattern != NULL )
|
||||
break;
|
||||
if( pTree == NULL ) {
|
||||
pElement->Release();
|
||||
return false;
|
||||
}
|
||||
pParent = NULL;
|
||||
hr = pTree->GetParentElement( pElement, &pParent );
|
||||
pElement->Release();
|
||||
pElement = pParent;
|
||||
bGoUp = TRUE;
|
||||
}
|
||||
if( pElement == NULL )
|
||||
return false;
|
||||
|
||||
if( !bGoUp ) {
|
||||
hr = pElement->get_CurrentBoundingRectangle( &r );
|
||||
if( hr == S_OK) {
|
||||
pt.x -= r.left;
|
||||
pt.y -= r.top;
|
||||
}
|
||||
}
|
||||
pElement->Release();
|
||||
|
||||
pTextRange = NULL;
|
||||
hr = pTextPattern->RangeFromPoint( pt, &pTextRange );
|
||||
pTextPattern->Release();
|
||||
if( hr != S_OK || pTextRange == NULL )
|
||||
return false;
|
||||
|
||||
hr = pTextRange->ExpandToEnclosingUnit( TextUnit_Word );
|
||||
if( hr == S_OK) {
|
||||
hr = pTextRange->GetText( 255, &bstr );
|
||||
if (hr == S_OK) {
|
||||
wsprintfW( buffer, L"%s", (LPCWSTR)bstr );
|
||||
SysFreeString( bstr );
|
||||
}
|
||||
}
|
||||
pTextRange->Release();
|
||||
|
||||
return ( buffer[0] != 0 );
|
||||
}
|
||||
|
||||
WCHAR *gdGetWordAtPointByAutomation( POINT pt )
|
||||
{
|
||||
if( gdAuto.getWordAtPoint( pt ) ) return gdAuto.getText();
|
||||
else return NULL;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef __WORD_BY_AUTO_HH_INCLUDED
|
||||
#define __WORD_BY_AUTO_HH_INCLUDED
|
||||
|
||||
WCHAR *gdGetWordAtPointByAutomation( POINT pt );
|
||||
|
||||
#endif
|
12
xdxf.cc
12
xdxf.cc
|
@ -147,16 +147,16 @@ public:
|
|||
|
||||
~XdxfDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -200,7 +200,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
void loadIcon() throw();
|
||||
void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -312,7 +312,7 @@ XdxfDictionary::~XdxfDictionary()
|
|||
dict_data_close( dz );
|
||||
}
|
||||
|
||||
void XdxfDictionary::loadIcon() throw()
|
||||
void XdxfDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
266
zim.cc
266
zim.cc
|
@ -78,7 +78,8 @@ enum CompressionType
|
|||
struct ZIM_header
|
||||
{
|
||||
quint32 magicNumber;
|
||||
quint32 version;
|
||||
quint16 majorVersion;
|
||||
quint16 minorVersion;
|
||||
quint8 uuid[ 16 ];
|
||||
quint32 articleCount;
|
||||
quint32 clusterCount;
|
||||
|
@ -125,7 +126,7 @@ __attribute__((packed))
|
|||
enum
|
||||
{
|
||||
Signature = 0x584D495A, // ZIMX on little-endian, XMIZ on big-endian
|
||||
CurrentFormatVersion = 1 + BtreeIndexing::FormatVersion + Folding::Version
|
||||
CurrentFormatVersion = 3 + BtreeIndexing::FormatVersion + Folding::Version
|
||||
};
|
||||
|
||||
struct IdxHeader
|
||||
|
@ -158,13 +159,15 @@ struct Cache
|
|||
quint32 clusterNumber;
|
||||
int stamp;
|
||||
int count, size;
|
||||
unsigned blobs_offset_size;
|
||||
|
||||
Cache() :
|
||||
data( 0 ),
|
||||
clusterNumber( 0 ),
|
||||
stamp( -1 ),
|
||||
count( 0 ),
|
||||
size( 0 )
|
||||
size( 0 ),
|
||||
blobs_offset_size( 0 )
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -184,13 +187,25 @@ public:
|
|||
}
|
||||
const ZIM_header & header() const
|
||||
{ return zimHeader; }
|
||||
string getClusterData( quint32 cluster_nom );
|
||||
|
||||
string getClusterData( quint32 cluster_nom, unsigned & blob_offset_size );
|
||||
|
||||
const QString getMimeType( quint16 nom )
|
||||
{ return mimeTypes.value( nom ); }
|
||||
|
||||
bool isArticleMime( quint16 mime_type )
|
||||
{ return getMimeType( mime_type ).startsWith( "text/html", Qt::CaseInsensitive )
|
||||
|| getMimeType( mime_type ).startsWith( "text/plain", Qt::CaseInsensitive ); }
|
||||
|
||||
|
||||
quint16 redirectedMimeType( RedirectEntry const & redEntry );
|
||||
|
||||
private:
|
||||
ZIM_header zimHeader;
|
||||
Cache cache[ CACHE_SIZE ];
|
||||
int stamp;
|
||||
QVector< QPair< quint64, quint32 > > clusterOffsets;
|
||||
QStringList mimeTypes;
|
||||
|
||||
void clearCache();
|
||||
};
|
||||
|
@ -291,10 +306,33 @@ bool ZimFile::open()
|
|||
|
||||
std::sort( clusterOffsets.begin(), clusterOffsets.end() );
|
||||
|
||||
// Read mime types
|
||||
|
||||
string type;
|
||||
char ch;
|
||||
|
||||
seek( zimHeader.mimeListPos );
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
type.clear();
|
||||
while( getChar( &ch ) )
|
||||
{
|
||||
if( ch == 0 )
|
||||
break;
|
||||
type.push_back( ch );
|
||||
}
|
||||
if( type.empty() )
|
||||
break;
|
||||
|
||||
QString s = QString::fromUtf8( type.c_str(), type.size() );
|
||||
mimeTypes.append( s );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
string ZimFile::getClusterData( quint32 cluster_nom )
|
||||
string ZimFile::getClusterData( quint32 cluster_nom, unsigned & blobs_offset_size )
|
||||
{
|
||||
// Check cache
|
||||
int target = 0;
|
||||
|
@ -328,6 +366,7 @@ string ZimFile::getClusterData( quint32 cluster_nom )
|
|||
if( found )
|
||||
{
|
||||
// Cache hit
|
||||
blobs_offset_size = cache[ target ].blobs_offset_size;
|
||||
return string( cache[ target ].data, cache[ target ].count );
|
||||
}
|
||||
|
||||
|
@ -353,9 +392,11 @@ string ZimFile::getClusterData( quint32 cluster_nom )
|
|||
|
||||
seek( clusterOffsets.at( nom ).first );
|
||||
|
||||
char compressionType;
|
||||
if( !getChar( &compressionType ) )
|
||||
char compressionType, cluster_info;
|
||||
if( !getChar( &cluster_info ) )
|
||||
return string();
|
||||
compressionType = cluster_info & 0x0F;
|
||||
blobs_offset_size = cluster_info & 0x10 && zimHeader.majorVersion >= 6 ? 8 : 4;
|
||||
|
||||
string decompressedData;
|
||||
|
||||
|
@ -384,9 +425,16 @@ string ZimFile::getClusterData( quint32 cluster_nom )
|
|||
// Check BLOBs number in the cluster
|
||||
// We cache multi-element clusters only
|
||||
|
||||
quint32 firstOffset;
|
||||
memcpy( &firstOffset, decompressedData.data(), sizeof(firstOffset) );
|
||||
quint32 blobCount = ( firstOffset - 4 ) / 4;
|
||||
quint32 firstOffset32;
|
||||
quint64 firstOffset;
|
||||
if( blobs_offset_size == 8 )
|
||||
memcpy( &firstOffset, decompressedData.data(), sizeof(firstOffset) );
|
||||
else
|
||||
{
|
||||
memcpy( &firstOffset32, decompressedData.data(), sizeof(firstOffset32) );
|
||||
firstOffset = firstOffset32;
|
||||
}
|
||||
quint32 blobCount = ( firstOffset - blobs_offset_size ) / blobs_offset_size;
|
||||
|
||||
if( blobCount > 1 )
|
||||
{
|
||||
|
@ -410,12 +458,52 @@ string ZimFile::getClusterData( quint32 cluster_nom )
|
|||
memcpy( cache[ target ].data, decompressedData.c_str(), size );
|
||||
cache[ target ].count = size;
|
||||
cache[ target ].clusterNumber = cluster_nom;
|
||||
cache[ target ].blobs_offset_size = blobs_offset_size;
|
||||
}
|
||||
}
|
||||
|
||||
return decompressedData;
|
||||
}
|
||||
|
||||
quint16 ZimFile::redirectedMimeType( RedirectEntry const & redEntry )
|
||||
{
|
||||
RedirectEntry current_entry = redEntry;
|
||||
quint64 current_pos = pos();
|
||||
quint16 mimetype = 0xFFFF;
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
quint32 current_nom = current_entry.redirectIndex;
|
||||
|
||||
seek( zimHeader.urlPtrPos + (quint64)current_nom * 8 );
|
||||
quint64 new_pos;
|
||||
if( read( reinterpret_cast< char * >( &new_pos ), sizeof(new_pos) ) != sizeof(new_pos) )
|
||||
break;
|
||||
|
||||
seek( new_pos );
|
||||
quint16 new_mimetype;
|
||||
if( read( reinterpret_cast< char * >( &new_mimetype ), sizeof(new_mimetype) ) != sizeof(new_mimetype) )
|
||||
break;
|
||||
|
||||
if( new_mimetype == 0xFFFF ) // Redirect to other article
|
||||
{
|
||||
if( read( reinterpret_cast< char * >( ¤t_entry ) + 2, sizeof( current_entry ) - 2 ) != sizeof( current_entry ) - 2 )
|
||||
break;
|
||||
if( current_nom == current_entry.redirectIndex )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mimetype = new_mimetype;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
seek( current_pos );
|
||||
return mimetype;
|
||||
}
|
||||
|
||||
|
||||
// Some supporting functions
|
||||
|
||||
bool indexIsOldOrBad( string const & indexFile )
|
||||
|
@ -516,23 +604,42 @@ quint32 readArticle( ZimFile & file, quint32 articleNumber, string & result,
|
|||
|
||||
// Read cluster data
|
||||
|
||||
string decompressedData = file.getClusterData( artEntry.clusterNumber );
|
||||
unsigned offset_size = 0;
|
||||
string decompressedData = file.getClusterData( artEntry.clusterNumber, offset_size );
|
||||
if( decompressedData.empty() )
|
||||
break;
|
||||
|
||||
// Take article data from cluster
|
||||
|
||||
quint32 firstOffset;
|
||||
memcpy( &firstOffset, decompressedData.data(), sizeof(firstOffset) );
|
||||
quint32 blobCount = ( firstOffset - 4 ) / 4;
|
||||
quint32 firstOffset32;
|
||||
quint64 firstOffset;
|
||||
|
||||
if( offset_size == 8 )
|
||||
memcpy( &firstOffset, decompressedData.data(), sizeof(firstOffset) );
|
||||
else
|
||||
{
|
||||
memcpy( &firstOffset32, decompressedData.data(), sizeof(firstOffset32) );
|
||||
firstOffset = firstOffset32;
|
||||
}
|
||||
quint32 blobCount = ( firstOffset - offset_size ) / offset_size;
|
||||
if( artEntry.blobNumber > blobCount )
|
||||
break;
|
||||
|
||||
quint32 offsets[ 2 ];
|
||||
memcpy( offsets, decompressedData.data() + artEntry.blobNumber * 4, sizeof(offsets) );
|
||||
quint32 size = offsets[ 1 ] - offsets[ 0 ];
|
||||
|
||||
result.append( decompressedData, offsets[ 0 ], size );
|
||||
quint32 size;
|
||||
if( offset_size == 8 )
|
||||
{
|
||||
quint64 offsets[ 2 ];
|
||||
memcpy( offsets, decompressedData.data() + artEntry.blobNumber * 8, sizeof(offsets) );
|
||||
size = offsets[ 1 ] - offsets[ 0 ];
|
||||
result.append( decompressedData, offsets[ 0 ], size );
|
||||
}
|
||||
else
|
||||
{
|
||||
quint32 offsets[ 2 ];
|
||||
memcpy( offsets, decompressedData.data() + artEntry.blobNumber * 4, sizeof(offsets) );
|
||||
size = offsets[ 1 ] - offsets[ 0 ];
|
||||
result.append( decompressedData, offsets[ 0 ], size );
|
||||
}
|
||||
|
||||
return articleNumber;
|
||||
}
|
||||
|
@ -562,16 +669,16 @@ class ZimDictionary: public BtreeIndexing::BtreeDictionary
|
|||
|
||||
~ZimDictionary();
|
||||
|
||||
virtual string getName() throw()
|
||||
virtual string getName() noexcept
|
||||
{ return dictionaryName; }
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.articleCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return idxHeader.wordCount; }
|
||||
|
||||
inline virtual quint32 getLangFrom() const
|
||||
|
@ -618,7 +725,7 @@ class ZimDictionary: public BtreeIndexing::BtreeDictionary
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -662,7 +769,7 @@ ZimDictionary::ZimDictionary( string const & id,
|
|||
{
|
||||
QString name = QDir::fromNativeSeparators( FsEncoding::decode( dictionaryFiles[ 0 ].c_str() ) );
|
||||
int n = name.lastIndexOf( '/' );
|
||||
dictionaryName = string( name.mid( n + 1 ).toUtf8().constData() );
|
||||
dictionaryName = name.mid( n + 1 ).toStdString();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -685,7 +792,7 @@ ZimDictionary::~ZimDictionary()
|
|||
df.close();
|
||||
}
|
||||
|
||||
void ZimDictionary::loadIcon() throw()
|
||||
void ZimDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
@ -1132,32 +1239,8 @@ sptr< Dictionary::DataRequest > ZimDictionary::getSearchResults( QString const &
|
|||
|
||||
/// ZimDictionary::getArticle()
|
||||
|
||||
class ZimArticleRequest;
|
||||
|
||||
class ZimArticleRequestRunnable: public QRunnable
|
||||
{
|
||||
ZimArticleRequest & r;
|
||||
QSemaphore & hasExited;
|
||||
|
||||
public:
|
||||
|
||||
ZimArticleRequestRunnable( ZimArticleRequest & r_,
|
||||
QSemaphore & hasExited_ ): r( r_ ),
|
||||
hasExited( hasExited_ )
|
||||
{}
|
||||
|
||||
~ZimArticleRequestRunnable()
|
||||
{
|
||||
hasExited.release();
|
||||
}
|
||||
|
||||
virtual void run();
|
||||
};
|
||||
|
||||
class ZimArticleRequest: public Dictionary::DataRequest
|
||||
{
|
||||
friend class ZimArticleRequestRunnable;
|
||||
|
||||
wstring word;
|
||||
vector< wstring > alts;
|
||||
ZimDictionary & dict;
|
||||
|
@ -1173,11 +1256,10 @@ public:
|
|||
ZimDictionary & dict_, bool ignoreDiacritics_ ):
|
||||
word( word_ ), alts( alts_ ), dict( dict_ ), ignoreDiacritics( ignoreDiacritics_ )
|
||||
{
|
||||
QThreadPool::globalInstance()->start(
|
||||
new ZimArticleRequestRunnable( *this, hasExited ) );
|
||||
QThreadPool::globalInstance()->start( [ this ]() { this->run(); } );
|
||||
}
|
||||
|
||||
void run(); // Run from another thread by ZimArticleRequestRunnable
|
||||
void run();
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
|
@ -1191,11 +1273,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void ZimArticleRequestRunnable::run()
|
||||
{
|
||||
r.run();
|
||||
}
|
||||
|
||||
void ZimArticleRequest::run()
|
||||
{
|
||||
if ( Utils::AtomicInt::loadAcquire( isCancelled ) )
|
||||
|
@ -1336,32 +1413,8 @@ sptr< Dictionary::DataRequest > ZimDictionary::getArticle( wstring const & word,
|
|||
|
||||
//// ZimDictionary::getResource()
|
||||
|
||||
class ZimResourceRequest;
|
||||
|
||||
class ZimResourceRequestRunnable: public QRunnable
|
||||
{
|
||||
ZimResourceRequest & r;
|
||||
QSemaphore & hasExited;
|
||||
|
||||
public:
|
||||
|
||||
ZimResourceRequestRunnable( ZimResourceRequest & r_,
|
||||
QSemaphore & hasExited_ ): r( r_ ),
|
||||
hasExited( hasExited_ )
|
||||
{}
|
||||
|
||||
~ZimResourceRequestRunnable()
|
||||
{
|
||||
//hasExited.release();
|
||||
}
|
||||
|
||||
virtual void run();
|
||||
};
|
||||
|
||||
class ZimResourceRequest: public Dictionary::DataRequest
|
||||
{
|
||||
friend class ZimResourceRequestRunnable;
|
||||
|
||||
ZimDictionary & dict;
|
||||
|
||||
string resourceName;
|
||||
|
@ -1372,12 +1425,10 @@ class ZimResourceRequest: public Dictionary::DataRequest
|
|||
public:
|
||||
ZimResourceRequest(ZimDictionary &dict_, string const &resourceName_)
|
||||
: dict(dict_), resourceName(resourceName_) {
|
||||
//(new ZimResourceRequestRunnable(*this, hasExited))->run();
|
||||
QThreadPool::globalInstance()->start(
|
||||
new ZimResourceRequestRunnable( *this, hasExited ) );
|
||||
QThreadPool::globalInstance()->start( [ this ]() { this->run(); } );
|
||||
}
|
||||
|
||||
void run(); // Run from another thread by ZimResourceRequestRunnable
|
||||
void run();
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
|
@ -1391,11 +1442,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void ZimResourceRequestRunnable::run()
|
||||
{
|
||||
r.run();
|
||||
}
|
||||
|
||||
void ZimResourceRequest::run()
|
||||
{
|
||||
// Some runnables linger enough that they are cancelled before they start
|
||||
|
@ -1498,6 +1544,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
|
||||
df.open();
|
||||
ZIM_header const & zh = df.header();
|
||||
bool new_namespaces = ( zh.majorVersion >= 6 && zh.minorVersion >= 1 );
|
||||
|
||||
if( zh.magicNumber != 0x44D495A )
|
||||
throw exNotZimFile( i->c_str() );
|
||||
|
@ -1534,7 +1581,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
}
|
||||
|
||||
const quint64 * ptr;
|
||||
quint16 mimetype;
|
||||
quint16 mimetype, redirected_mime = 0xFFFF;
|
||||
ArticleEntry artEntry;
|
||||
RedirectEntry redEntry;
|
||||
string url, title;
|
||||
|
@ -1551,6 +1598,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
if( ret != sizeof(RedirectEntry) - 2 )
|
||||
throw exCantReadFile( i->c_str() );
|
||||
|
||||
redirected_mime = df.redirectedMimeType( redEntry );
|
||||
nameSpace = redEntry.nameSpace;
|
||||
}
|
||||
else
|
||||
|
@ -1562,7 +1610,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
|
||||
nameSpace = artEntry.nameSpace;
|
||||
|
||||
if( nameSpace == 'A' )
|
||||
if( ( nameSpace == 'A' || ( nameSpace == 'C' && new_namespaces ) ) && df.isArticleMime( mimetype ) )
|
||||
articleCount++;
|
||||
}
|
||||
|
||||
|
@ -1585,7 +1633,8 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
title.push_back( ch );
|
||||
}
|
||||
|
||||
if( nameSpace == 'A' )
|
||||
if( nameSpace == 'A' || ( nameSpace == 'C' && new_namespaces && ( df.isArticleMime( mimetype )
|
||||
|| ( mimetype == 0xFFFF && df.isArticleMime( redirected_mime ) ) ) ) )
|
||||
{
|
||||
wstring word;
|
||||
if( !title.empty() )
|
||||
|
@ -1593,16 +1642,26 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
else
|
||||
word = Utf8::decode( url );
|
||||
|
||||
if( maxHeadwordsToExpand && zh.articleCount >= maxHeadwordsToExpand )
|
||||
indexedWords.addSingleWord( word, n );
|
||||
if( df.isArticleMime( mimetype )
|
||||
|| ( mimetype == 0xFFFF && df.isArticleMime( redirected_mime ) ) )
|
||||
{
|
||||
if( maxHeadwordsToExpand && zh.articleCount >= maxHeadwordsToExpand )
|
||||
indexedWords.addSingleWord( word, n );
|
||||
else
|
||||
indexedWords.addWord( word, n );
|
||||
wordCount++;
|
||||
}
|
||||
else
|
||||
indexedWords.addWord( word, n );
|
||||
wordCount++;
|
||||
{
|
||||
url.insert( url.begin(), '/' );
|
||||
url.insert( url.begin(), nameSpace );
|
||||
indexedResources.addSingleWord( Utf8::decode( url ), n );
|
||||
}
|
||||
}
|
||||
else
|
||||
if( nameSpace == 'M' )
|
||||
{
|
||||
if( url.compare( "Title") == 0 )
|
||||
if( url.compare( "Title" ) == 0 )
|
||||
{
|
||||
idxHeader.namePtr = n;
|
||||
string name;
|
||||
|
@ -1610,10 +1669,10 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
initializing.indexingDictionary( name );
|
||||
}
|
||||
else
|
||||
if( url.compare( "Description") == 0 )
|
||||
if( url.compare( "Description" ) == 0 )
|
||||
idxHeader.descriptionPtr = n;
|
||||
else
|
||||
if( url.compare( "Language") == 0 )
|
||||
if( url.compare( "Language" ) == 0 )
|
||||
{
|
||||
string lang;
|
||||
readArticle( df, n, lang );
|
||||
|
@ -1626,6 +1685,11 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
|
|||
}
|
||||
}
|
||||
else
|
||||
if( nameSpace == 'X' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
url.insert( url.begin(), '/' );
|
||||
url.insert( url.begin(), nameSpace );
|
||||
|
|
14
zipsounds.cc
14
zipsounds.cc
|
@ -114,15 +114,15 @@ public:
|
|||
ZipSoundsDictionary( string const & id, string const & indexFile,
|
||||
vector< string > const & dictionaryFiles );
|
||||
|
||||
virtual string getName() throw();
|
||||
virtual string getName() noexcept;
|
||||
|
||||
virtual map< Dictionary::Property, string > getProperties() throw()
|
||||
virtual map< Dictionary::Property, string > getProperties() noexcept
|
||||
{ return map< Dictionary::Property, string >(); }
|
||||
|
||||
virtual unsigned long getArticleCount() throw()
|
||||
virtual unsigned long getArticleCount() noexcept
|
||||
{ return idxHeader.soundsCount; }
|
||||
|
||||
virtual unsigned long getWordCount() throw()
|
||||
virtual unsigned long getWordCount() noexcept
|
||||
{ return getArticleCount(); }
|
||||
|
||||
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
|
||||
|
@ -136,7 +136,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void loadIcon() throw();
|
||||
virtual void loadIcon() noexcept;
|
||||
};
|
||||
|
||||
ZipSoundsDictionary::ZipSoundsDictionary( string const & id,
|
||||
|
@ -164,7 +164,7 @@ ZipSoundsDictionary::ZipSoundsDictionary( string const & id,
|
|||
|
||||
}
|
||||
|
||||
string ZipSoundsDictionary::getName() throw()
|
||||
string ZipSoundsDictionary::getName() noexcept
|
||||
{
|
||||
string result = FsEncoding::basename( getDictionaryFilenames()[ 0 ] );
|
||||
|
||||
|
@ -384,7 +384,7 @@ sptr< Dictionary::DataRequest > ZipSoundsDictionary::getResource( string const &
|
|||
return new Dictionary::DataRequestInstant( false );
|
||||
}
|
||||
|
||||
void ZipSoundsDictionary::loadIcon() throw()
|
||||
void ZipSoundsDictionary::loadIcon() noexcept
|
||||
{
|
||||
if ( dictionaryIconLoaded )
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue