aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaturneric <[email protected]>2021-07-20 16:42:50 +0000
committerSaturneric <[email protected]>2021-07-20 16:42:50 +0000
commitc57feb6a678e27140bb9ae7d132b641947514c31 (patch)
tree5ed7a7728c084214ce858323a4eccdcba98200b6
parentUpdate Workflow (diff)
parentFix problem that macos cannot use multi-languages. (diff)
downloadGpgFrontend-c57feb6a678e27140bb9ae7d132b641947514c31.tar.gz
GpgFrontend-c57feb6a678e27140bb9ae7d132b641947514c31.zip
Merge branch 'develop' into develop-ci
-rw-r--r--.github/workflows/codeql-analysis.yml128
-rw-r--r--.github/workflows/debug.yml2
-rw-r--r--.github/workflows/release.yml17
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt2
-rw-r--r--README.md123
-rw-r--r--README_CN.md102
-rw-r--r--gpgfrontend.qrc2
-rw-r--r--include/GpgFrontend.h.in38
-rw-r--r--include/GpgFrontendBuildInfo.h.in (renamed from include/GpgFrontendBuildInfo.h)21
-rw-r--r--include/MainWindow.h21
-rw-r--r--include/Mime.h130
-rw-r--r--include/gpg/GpgContext.h19
-rw-r--r--include/rapidjson/allocators.h271
-rw-r--r--include/rapidjson/document.h2575
-rw-r--r--include/rapidjson/encodedstream.h299
-rw-r--r--include/rapidjson/encodings.h716
-rw-r--r--include/rapidjson/error/en.h74
-rw-r--r--include/rapidjson/error/error.h155
-rw-r--r--include/rapidjson/filereadstream.h99
-rw-r--r--include/rapidjson/filewritestream.h104
-rw-r--r--include/rapidjson/fwd.h151
-rw-r--r--include/rapidjson/internal/biginteger.h290
-rw-r--r--include/rapidjson/internal/diyfp.h258
-rw-r--r--include/rapidjson/internal/dtoa.h245
-rw-r--r--include/rapidjson/internal/ieee754.h78
-rw-r--r--include/rapidjson/internal/itoa.h304
-rw-r--r--include/rapidjson/internal/meta.h181
-rw-r--r--include/rapidjson/internal/pow10.h55
-rw-r--r--include/rapidjson/internal/regex.h701
-rw-r--r--include/rapidjson/internal/stack.h230
-rw-r--r--include/rapidjson/internal/strfunc.h55
-rw-r--r--include/rapidjson/internal/strtod.h269
-rw-r--r--include/rapidjson/internal/swap.h46
-rw-r--r--include/rapidjson/istreamwrapper.h115
-rw-r--r--include/rapidjson/memorybuffer.h70
-rw-r--r--include/rapidjson/memorystream.h71
-rw-r--r--include/rapidjson/msinttypes/inttypes.h316
-rw-r--r--include/rapidjson/msinttypes/stdint.h300
-rw-r--r--include/rapidjson/ostreamwrapper.h81
-rw-r--r--include/rapidjson/pointer.h1358
-rw-r--r--include/rapidjson/prettywriter.h255
-rw-r--r--include/rapidjson/rapidjson.h615
-rw-r--r--include/rapidjson/reader.h1879
-rw-r--r--include/rapidjson/schema.h2006
-rw-r--r--include/rapidjson/stream.h179
-rw-r--r--include/rapidjson/stringbuffer.h117
-rw-r--r--include/rapidjson/writer.h610
-rw-r--r--include/smtp/SmtpMime31
-rw-r--r--include/smtp/emailaddress.h63
-rw-r--r--include/smtp/mimeattachment.h51
-rw-r--r--include/smtp/mimecontentformatter.h43
-rw-r--r--include/smtp/mimefile.h63
-rw-r--r--include/smtp/mimehtml.h61
-rw-r--r--include/smtp/mimeinlinefile.h56
-rw-r--r--include/smtp/mimemessage.h110
-rw-r--r--include/smtp/mimemultipart.h71
-rw-r--r--include/smtp/mimepart.h110
-rw-r--r--include/smtp/mimetext.h62
-rw-r--r--include/smtp/quotedprintable.h39
-rw-r--r--include/smtp/smtpclient.h197
-rw-r--r--include/smtp/smtpexports.h10
-rw-r--r--include/ui/AttachmentTableModel.h57
-rwxr-xr-xinclude/ui/QuitDialog.h33
-rw-r--r--include/ui/SendMailDialog.h66
-rwxr-xr-xinclude/ui/SettingsDialog.h26
-rw-r--r--include/ui/WaitingDialog.h2
-rw-r--r--include/ui/help/AboutDialog.h (renamed from include/ui/AboutDialog.h)25
-rw-r--r--include/ui/help/VersionCheckThread.h32
-rw-r--r--include/ui/keypair_details/KeyPairDetailTab.h10
-rw-r--r--include/ui/widgets/Attachments.h59
-rw-r--r--include/ui/widgets/FilePage.h5
-rw-r--r--include/ui/widgets/InfoBoardWidget.h4
-rw-r--r--include/ui/widgets/KeyList.h2
-rw-r--r--resource/gpgfrontend/usr/share/metainfo/pub.gpgfrontend.gpgfrontend.metainfo.xml35
-rw-r--r--resource/icons/refresh.pngbin0 -> 6821 bytes
-rw-r--r--resource/icons/up.pngbin0 -> 4557 bytes
-rw-r--r--resource/ts/gpgfrontend_en_us.ts1315
-rw-r--r--resource/ts/gpgfrontend_es.ts (renamed from resource/ts/gpgfrontend_zh_cht.ts)2479
-rw-r--r--resource/ts/gpgfrontend_fr.ts (renamed from resource/ts/gpg_frontend_fr.ts)2401
-rw-r--r--resource/ts/gpgfrontend_ru.ts (renamed from resource/ts/gpg_frontend_ru.ts)2429
-rw-r--r--resource/ts/gpgfrontend_zh_cn.ts (renamed from resource/ts/gpgfrontend_zh_chs.ts)2461
-rw-r--r--src/CMakeLists.txt14
-rw-r--r--src/MainWindow.cpp387
-rw-r--r--src/Mime.cpp233
-rw-r--r--src/gpg/GpgContext.cpp164
-rw-r--r--src/main.cpp3
-rw-r--r--src/smtp/CMakeLists.txt6
-rw-r--r--src/smtp/emailaddress.cpp44
-rw-r--r--src/smtp/mimeattachment.cpp43
-rw-r--r--src/smtp/mimecontentformatter.cpp59
-rw-r--r--src/smtp/mimefile.cpp61
-rw-r--r--src/smtp/mimehtml.cpp46
-rw-r--r--src/smtp/mimeinlinefile.cpp42
-rw-r--r--src/smtp/mimemessage.cpp308
-rw-r--r--src/smtp/mimemultipart.cpp70
-rw-r--r--src/smtp/mimepart.cpp159
-rw-r--r--src/smtp/mimetext.cpp52
-rw-r--r--src/smtp/quotedprintable.cpp62
-rw-r--r--src/smtp/smtpclient.cpp407
-rw-r--r--src/ui/AboutDialog.cpp94
-rw-r--r--src/ui/AttachmentTableModel.cpp134
-rw-r--r--src/ui/CMakeLists.txt1
-rwxr-xr-xsrc/ui/FileEncryptionDialog.cpp37
-rwxr-xr-xsrc/ui/KeyMgmt.cpp2
-rw-r--r--src/ui/KeyServerImportDialog.cpp10
-rw-r--r--src/ui/KeyUploadDialog.cpp4
-rw-r--r--src/ui/SendMailDialog.cpp173
-rwxr-xr-xsrc/ui/SettingsDialog.cpp1143
-rw-r--r--src/ui/WaitingDialog.cpp9
-rw-r--r--src/ui/Wizard.cpp44
-rw-r--r--src/ui/help/AboutDialog.cpp215
-rw-r--r--src/ui/help/VersionCheckThread.cpp55
-rw-r--r--src/ui/keygen/KeygenDialog.cpp5
-rw-r--r--src/ui/keygen/SubkeyGenerateThread.cpp2
-rw-r--r--src/ui/keypair_details/KeyPairDetailTab.cpp85
-rw-r--r--src/ui/keypair_details/KeyPairSubkeyTab.cpp4
-rw-r--r--src/ui/keypair_details/KeyPairUIDTab.cpp7
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp324
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp13
-rw-r--r--src/ui/main_window/MainWindowUI.cpp41
-rw-r--r--src/ui/widgets/Attachments.cpp180
-rw-r--r--src/ui/widgets/EditorPage.cpp3
-rw-r--r--src/ui/widgets/FilePage.cpp57
-rw-r--r--src/ui/widgets/InfoBoardWidget.cpp16
-rw-r--r--src/ui/widgets/KeyList.cpp5
-rw-r--r--src/ui/widgets/TextEdit.cpp11
127 files changed, 26109 insertions, 6867 deletions
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 00000000..c50377b9
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,128 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ main ]
+ schedule:
+ - cron: '19 14 * * 2'
+
+env:
+ # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+ BUILD_TYPE: Debug
+ EXECUTABLE_OUTPUT_PATH: ./
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'cpp' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
+ # Learn more:
+ # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+ - name: Install Dependence (Linux)
+ run: |
+ sudo apt-get update
+ sudo apt-get -y install build-essential binutils git autoconf automake gettext texinfo
+ sudo apt-get -y install gcc g++
+ sudo apt-get -y install gpgsm
+ - name: Cache Qt
+ id: cache-qt
+ uses: actions/cache@v1
+ with:
+ path: ../Qt
+ key: ${{ runner.os }}-QtCache
+
+ - name: Install Qt
+ uses: jurplel/install-qt-action@v2
+ with:
+ cached: ${{ steps.cache-qt.outputs.cache-hit }}
+
+ - name: Build gpg-error (Linux)
+ run: |
+ cd ${{github.workspace}}/..
+ git clone https://github.com/saturneric/libgpg-error
+ cd libgpg-error
+ ./autogen.sh
+ ./configure --enable-maintainer-mode --enable-static=yes && make -j2
+ sudo make install
+ cd ${{github.workspace}}
+
+ - name: Build assuan (Linux)
+ run: |
+ cd ${{github.workspace}}/..
+ git clone https://github.com/saturneric/libassuan
+ cd libassuan
+ ./autogen.sh
+ ./configure --enable-maintainer-mode --enable-static=yes && make -j2
+ sudo make install
+ cd ${{github.workspace}}
+
+ - name: Build GpgME (Linux)
+ run: |
+ cd ${{github.workspace}}/..
+ git clone https://github.com/saturneric/gpgme
+ cd gpgme
+ ./autogen.sh
+ ./configure --enable-maintainer-mode --enable-static=yes --enable-languages=cpp && make -j2
+ sudo make install
+ cd ${{github.workspace}}
+
+ - name: Configure CMake
+ # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
+ # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
+ run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DEXECUTABLE_OUTPUT_PATH=${{env.EXECUTABLE_OUTPUT_PATH}}
+
+ - name: Build GpgFrontend
+ # Build your program with the given configuration
+ run: cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -j 2
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://git.io/JvXDl
+
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/debug.yml b/.github/workflows/debug.yml
index 2de9716c..11194af0 100644
--- a/.github/workflows/debug.yml
+++ b/.github/workflows/debug.yml
@@ -123,7 +123,7 @@ jobs:
- name: Build GpgFrontend
# Build your program with the given configuration
- run: cmake --build ${{github.workspace}}/build --config $env.BUILD_TYPE}} -- -j 2
+ run: cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -j 2
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
- name: Configure CMake & Build Binary(Windows)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 8ec9f553..6a67d524 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -88,7 +88,7 @@ jobs:
shell: msys2 {0}
run: |
pacman --noconfirm -S --needed mingw-w64-x86_64-gcc mingw-w64-x86_64-make mingw-w64-x86_64-cmake autoconf automake mingw-w64-x86_64-qt-creator mingw-w64-x86_64-gpgme
- pacman --noconfirm -S --needed make texinfo
+ pacman --noconfirm -S --needed make texinfo zip
if: matrix.os == 'windows-latest'
- name: Build gpg-error (Linux)
@@ -142,9 +142,13 @@ jobs:
- name: Build GpgFrontend
# Build your program with the given configuration
- run: cmake --build ${{github.workspace}}/build --config $env.BUILD_TYPE}} -- -j 2
+ run: cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -j 2
if: matrix.os == 'ubuntu-16.04' || matrix.os == 'macos-latest'
+ - name: Get Short SHA of Commit
+ id: vars
+ run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
+
- name: Package App Bundle (macOS)
run: |
macdeployqt ${{github.workspace}}/build/release/GpgFrontend.app
@@ -154,12 +158,13 @@ jobs:
mkdir ${{github.workspace}}/build/artifactOut
hdiutil convert ${{github.workspace}}/build/tmp/tmp.dmg -format UDZO -o ${{github.workspace}}/build/artifactOut/GpgFrontend.dmg
codesign -s "Developer ID Application: Yu Hu (4279AWUL3X)" GpgFrontend.dmg
+ mv ${{github.workspace}}/build/artifactOut/GpgFrontend.dmg ${{github.workspace}}/build/artifactOut/GpgFrontend-${{steps.vars.outputs.sha_short}}-x86_64.dmg
if: matrix.os == 'macos-latest'
- name: Notarize Release Build (macOS)
uses: devbotsxyz/xcode-notarize@v1
with:
- product-path: "Export/Rings.app"
+ product-path: ${{github.workspace}}/build/artifactOut/GpgFrontend-${{steps.vars.outputs.sha_short}}-x86_64.dmg
appstore-connect-username: ${{ secrets.APPLE_DEVELOPER_ID }}
appstore-connect-password: ${{ secrets.APPLE_DEVELOPER_ID_SECRET }}
if: matrix.os == 'macos-latest'
@@ -173,7 +178,7 @@ jobs:
./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/release/gpgfrontend/usr/share/applications/*.desktop -appimage
if: matrix.os == 'ubuntu-16.04'
- - name: Configure CMake & Build Binary(Windows)
+ - name: Configure CMake & Build Binary (Windows)
shell: msys2 {0}
run: |
cd $(echo "/${{github.workspace}}" | sed 's/\\/\//g' | sed 's/://')
@@ -183,10 +188,6 @@ jobs:
cmake --build . --config ${{env.BUILD_TYPE}} -- -j 2
if: matrix.os == 'windows-latest'
- - name: Get Short SHA of Commit
- id: vars
- run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
-
- name: Upload Artifact(Linux)
uses: actions/upload-artifact@master
with:
diff --git a/.gitignore b/.gitignore
index f6db21d9..986db60c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
# Project
include/GpgFrontend.h
+include/GpgFrontendBuildInfo.h
#CLion
.idea/*
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c11b26af..f80087c3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)
-project(GpgFrontend VERSION 1.1.0 LANGUAGES CXX)
+project(GpgFrontend VERSION 1.2.2 LANGUAGES CXX)
message(STATUS "GPGFrontend Build Configuration Started CMAKE Version ${CMAKE_VERSION}")
diff --git a/README.md b/README.md
index c5b667e3..eb6337a0 100644
--- a/README.md
+++ b/README.md
@@ -5,28 +5,28 @@
![Language](https://img.shields.io/badge/language-C%2B%2B-green)
![License](https://img.shields.io/badge/License-GPL--3.0-orange)
![CodeSize](https://img.shields.io/github/languages/code-size/saturneric/GpgFrontend)
-[![Codacy Badge](https://app.codacy.com/project/badge/Grade/d1750e052a85430a8f1f84e58a0fceda)](https://www.codacy.com/gh/saturneric/GpgFrontend/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=saturneric/GpgFrontend&amp;utm_campaign=Badge_Grade)
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/d1750e052a85430a8f1f84e58a0fceda)](https://www.codacy.com/gh/saturneric/GpgFrontend/dashboard?utm_source=github.com&utm_medium=referral&utm_content=saturneric/GpgFrontend&utm_campaign=Badge_Grade)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/saturneric/gpgfrontend)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend.svg?type=small)](https://app.fossa.com/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend?ref=badge_small)
-GpgFrontend is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free [OpenPGP](https://www.openpgp.org/)
+GpgFrontend is a Powerful, Easy-to-Use, Compact, Cross-Platform, and
+Installation-Free [OpenPGP](https://www.openpgp.org/)
Crypto Tool.
-By using GpgFrontend, you can quickly **encrypt and decrypt text or files**. Or at the same time as the above
-operations, you can add **your own signature** to let others know that this document or this paragraph of text was
-issued by you. It aims to allow ordinary users to quickly use gpg and make professional users more convenient.
-GpgFrontend supports new features of OpenPGP.
+By using GpgFrontend, you can quickly encrypt and decrypt text or files. Or at the same time as the above operations,
+you can add your own signature to let others know that this document or this paragraph of text was issued by you.
+Please **take the initiative to protect privacy in your own hands**, instead of relying on servers and algorithms
+provided by large companies.
**Notice:** GpgFrontend does not provide an embedded [gnupg](https://gnupg.org/) binary library and needs to be
-installed by the user. **This is to ensure safety and avoid code or binary files involved in encryption and decryption being implanted in the backdoor during
-the delivery process.**
+installed by the user. **This is to ensure safety and avoid code or binary files involved in encryption and decryption
+being implanted in the backdoor during the delivery process.**
-[>> Quick Start](#quick-start)
-
-[>> Code & Binary Security](https://saturneric.github.io/GpgFrontend/index.html#/about/code-binary-verify)
-
-[>> 中文文档](https://github.com/saturneric/GpgFrontend/blob/main/README_CN.md)
+If you find this tool useful and promising, welcome to encourage me through STAR this project. Thanks!
+[>> Quick Start <<](#quick-start) |
+[>> Code & Binary Security <<](https://gpgfrontend.pub/#/about/code-binary-verify) |
+[>> 简中README <<](https://github.com/saturneric/GpgFrontend/blob/main/README_CN.md)
<div align="center">
<img width="640" src="https://github.com/saturneric/Blob/blob/master/screenshots/main_mac.jpg?raw=true" alt="macOS Screenshot"/>
@@ -54,6 +54,7 @@ the delivery process.**
- [Document](#document)
- [Purpose](#purpose)
- [Build](#build)
+- [Languages Support](#languages-support)
- [Contributing & Bugs Report](#contributing--bugs-report)
- [Contract](#contract)
- [Maintainers](#maintainers)
@@ -64,44 +65,48 @@ the delivery process.**
- Can run on **Windows, Linux and macOS**.
- Open source, free, no need to install.
- Just double-click, and then you can use it freely.
-- Supports multiple languages.
- - If you are interested, you can help
- me [translate the interface](https://saturneric.github.io/GpgFrontend/index.html#/translate-interface).
+- Supports multiple [languages](#languages-support).
## Usage
### Quick Start
-### Fast encryption
+### Fast Text Encryption
Encryption can be done in just a few clicks.
![GIF](https://github.com/saturneric/Blob/blob/master/gif/encrypt.gif?raw=true)
-### Fast Decryption
+### Fast Text Decryption
I want to see what you wrote right away.
![GIF](https://github.com/saturneric/Blob/blob/master/gif/decrypt.gif?raw=true)
+### Fast File Encryption & Sign
+
+What about files?
+
+![GIF](https://github.com/saturneric/Blob/blob/master/gif/encr-sign-file.gif?raw=true)
+
### More Helpful Operation
-Read the animated pictures in the [Document](https://saturneric.github.io/GpgFrontend/index.html#/) to learn more
-awesome operations.
+Read the animated pictures in the [Document](https://gpgfrontend.pub/#/quick-start) to learn more awesome operations.
### How to Run it
#### Windows
-1. [Download](https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.3.1_20210420.exe) `gnupg-w32-******.exe`
-2. Double Click it to install it
-3. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Windows Edition from the latest release
-4. Unzip `gpgfrontend-windows-latest-*******.zip`
-5. Go into the directory and double click `GpgFrontend.exe`.
+0. If you haven't installed gnupg,
+ please [Download](https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.3.1_20210420.exe) `gnupg-w32-******.exe` and
+ install it.
+1. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Windows Edition from the latest release
+2. Unzip `gpgfrontend-windows-latest-*******.zip`
+3. Go into the directory and double click `GpgFrontend.exe`.
#### macOS
-0. If command `gpg` is not avaliable, please use homebrew to install it first.
+0. If command `gpg` is not available, please use homebrew to install it first.
1. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) macOS edition from the latest release
2. Double-Click GpgFrontend.dmg to load it
- macOS will automatically decompress the zip file and then you will be able to see the dmg
@@ -111,28 +116,28 @@ awesome operations.
#### Debian/Ubuntu/CentOS
-1. Install gnupg (If you have already followed please skip)
+[![!AppImage](https://docs.appimage.org/_images/download-appimage-banner.svg)](https://github.com/saturneric/GpgFrontend/releases/latest)
+
+0. Install gnupg (If you have already followed please skip)
- For Debian/Ubuntu
- ```shell
- $ sudo apt update
- $ sudo apt install gpg
- ```
+ ```shell
+ $ sudo apt update
+ $ sudo apt install gpg
+ ```
- For CentOS
```shell
$ sudo yum install gnupg
```
-2. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Linux edition from the latest release
-3. Unzip gpgfrontend-ubuntu-16.04-*******.zip
- - `ubuntu-16.04` shows that Linux distributions at the same time as 16.04 or later are supported.
-4. Give `GpgFrontend-***.AppImage` permission to execute
+1. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Linux edition from the latest release
+2. Give `GpgFrontend-***.AppImage` permission to execute
```shell
$ chmod u+x ./GpgFrontend-***.AppImage
```
-5. Just double-click `GpgFrontend-***.AppImage` to run it.
+3. Just double-click `GpgFrontend-***.AppImage` to run it.
## Document
-For more usage information, please read [Document](https://saturneric.github.io/GpgFrontend/index.html#/).
+for more usage information, please read [document](https://gpgfrontend.pub/#/overview).
## Purpose
@@ -149,7 +154,26 @@ The GpgFrontend project is as open source, and it also insists on using open sou
## Build
-The tutorial for building the software will be released shortly. Before the relevant documents are released, you can refer to the project-related Github Action file if you know it.
+The tutorial for building the software will be released shortly. Before the relevant documents are released, you can
+refer to the project-related Github Action file if you know it.
+
+## Languages Support
+
+The supported languages are listed here. Some languages use machine translation and have not been verified. If you want
+to join translation and verification work, please refer to
+the [translate the interface](https://gpgfrontend.pub/#/translate-interface).
+
+Notice: The verification may not be complete and rigorous.
+
+| Language | English | 简体中文 | français | Французский | Español |
+| ---- | ---- | ---- | ---- | ---- | ---- |
+| Support | Support | 支持 | Etre prêt | ожидать | apoyar |
+| Verification | Origin | 不完全 | Jamais |Никогда | Nunca |
+
+| Language | 日本語 | 繁體中文 | عربى | português |
+| ---- | ---- | ---- | ---- | ---- |
+| Support | 未だに | 尚未 | ليس بعد | Ainda não |
+| Verification | | | | |
## Contract
@@ -171,19 +195,30 @@ Feel free to dive in! [Open an issue](https://github.com/saturneric/GpgFrontend/
GpgFrontend itself is licensed under the [GPLv3](COPYING).
+[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend?ref=badge_large)
+
+### Dependency
+
There are some libraries and binary included in the zip-file which (may) have different licenses, for more information
check their homepages. You can also obtain the sources from there.
-gpg4usb: https://www.gpg4usb.org/
+gnupg: https://gnupg.org/
-Gnupg: https://gnupg.org/
+gpg4usb: https://www.gpg4usb.org/
-QT: https://www.qt.io/
+QT 5.15.2(opensource): https://www.qt.io/
MSYS2: https://www.msys2.org/
mingw-w64: http://mingw-w64.org/doku.php
-The icons of this software use materials from Alibaba vector icon library. The Alibaba vector icon library is free to
-use. The icons in the free library aren't registered as trademarks. There is no copyright issue involved and can be used
-commercially.
+AppImage: https://appimage.org/
+
+rapidjson: https://github.com/Tencent/rapidjson
+
+Application
+Bundles: [Link](https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1)
+
+The icons of this software use materials from [Alibaba Iconfont](!https://www.iconfont.cn/). The Alibaba vector icon
+library is free to use. The icons in the free library aren't registered as trademarks. There is no copyright issue
+involved and can be used commercially.
diff --git a/README_CN.md b/README_CN.md
index e2f524df..e86a62e3 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -5,20 +5,21 @@
![Language](https://img.shields.io/badge/language-C%2B%2B-green)
![License](https://img.shields.io/badge/License-GPL--3.0-orange)
![CodeSize](https://img.shields.io/github/languages/code-size/saturneric/GpgFrontend)
-[![Codacy Badge](https://app.codacy.com/project/badge/Grade/d1750e052a85430a8f1f84e58a0fceda)](https://www.codacy.com/gh/saturneric/GpgFrontend/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=saturneric/GpgFrontend&amp;utm_campaign=Badge_Grade)
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/d1750e052a85430a8f1f84e58a0fceda)](https://www.codacy.com/gh/saturneric/GpgFrontend/dashboard?utm_source=github.com&utm_medium=referral&utm_content=saturneric/GpgFrontend&utm_campaign=Badge_Grade)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/saturneric/gpgfrontend)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend.svg?type=small)](https://app.fossa.com/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend?ref=badge_small)
GpgFrontend 是一个易于使用、小巧、跨平台和免安装的 [OpenPGP](https://www.openpgp.org/) 加密解密签名工具。
-通过使用 GpgFrontend,你可以快速加密和解密文本或文件。或者在进行上述操作的同时加上自己的签名,让别人知道这个文件或者这段文字是出自你之手。
-该软件旨在让普通用户更快上手gpg工具,让专业用户更便捷。 GpgFrontend 支持 OpenPGP 的新特性。
+通过使用 GpgFrontend,你可以快速加密和解密文本或文件。或者在进行上述操作的同时加上自己的签名,让别人知道这个文件或者这段文字是出自你之手。 请将隐私保护的主动权掌握在自己手上,而不是依赖大公司提供的服务器和算法。
-注意:GpgFrontend 不提供嵌入式 gnupg 二进制库,需要用户自行安装。这是为了确保安全,避免代码或二进制文件在传递过程中被植入后门。
+注意:GpgFrontend 不提供嵌入式 gnupg 二进制库,需要用户自行安装。这是为了确保安全,避免涉及加密解密的代码或二进制文件在传递过程中被植入后门。
+
+如果你觉得这款工具有用或者有希望,`欢迎通过STAR这个项目来鼓励我`。
[>> 快速开始](#quick-start)
-[>> 代码与二进制文件安全](https://saturneric.github.io/GpgFrontend/index.html#/about/code-binary-verify)
+[>> 代码与二进制文件安全](https://gpgfrontend.pub/#/about/code-binary-verify)
<div align="center">
<img width="640" src="https://github.com/saturneric/Blob/blob/master/screenshots/main_mac.jpg?raw=true" alt="macOS Screenshot"/>
@@ -47,8 +48,8 @@ GpgFrontend 是一个易于使用、小巧、跨平台和免安装的 [OpenPGP](
- [开发宗旨](#开发宗旨)
- [构建方法](#构建方法)
- [联系](#联系)
- - [做出贡献](#做出贡献)
- - [维护者](#维护者)
+ - [做出贡献或者报告问题](#做出贡献或者报告问题)
+ - [关于维护者](#关于维护者)
- [许可证](#许可证)
## 软件特性
@@ -57,7 +58,7 @@ GpgFrontend 是一个易于使用、小巧、跨平台和免安装的 [OpenPGP](
- 开源,免费,无需安装。
- 只需双击即可自由使用。
- 支持多种语言。
- - 有兴趣的可以帮我 [翻译一下界面](https://saturneric.github.io/GpgFrontend/index.html#/translate-interface) 。
+ - 有兴趣的可以帮我 [翻译一下界面](https://gpgfrontend.pub/#/translate-interface) 。
## 使用方法
@@ -75,79 +76,81 @@ GpgFrontend 是一个易于使用、小巧、跨平台和免安装的 [OpenPGP](
![GIF](https://github.com/saturneric/Blob/blob/master/gif/decrypt.gif?raw=true)
+### 快速文件加密与签名
+
+对于文件,我该怎么做?
+
+![GIF](https://github.com/saturneric/Blob/blob/master/gif/encr-sign-file.gif?raw=true)
+
### 还有那些有用的操作
-阅读 [文档](https://saturneric.github.io/GpgFrontend/index.html#/) 中的动图,了解更多精彩操作。
+阅读 [文档](https://gpgfrontend.pub/#/quick-start) 中的动图,了解更多精彩操作。
### 如何安装
#### Windows
-1. [下载](https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.3.1_20210420.exe) gnupg-w32-******.exe
-2. 双击安装
-3. [下载 GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Windows Edition from release
-4. 解压 gpgfrontend-windows-latest-*******.zip
-5. 进入目录,双击运行 GpgFrontend.exe
+0. 如果你还没有安装gnupg,请 [下载](https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.3.1_20210420.exe) gnupg-w32-**\*\***.exe 并双击安装
+1. [下载 GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Windows Edition from release
+2. 解压 gpgfrontend-windows-latest-**\*\*\***.zip
+3. 进入目录,双击运行 GpgFrontend.exe
#### macOS
-0. 如果命令 `gpg` 不可用,请先用Homebrew安装它.
+0. 如果命令 `gpg` 不可用,请先用 Homebrew 安装它.
1. [下载 GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) macOS edition from release
-2. 双击并加载 GpgFrontend.dmg
+2. 双击并加载 GpgFrontend-***.dmg
3. 双击并运行
- (由于macOS的安全策略,在真正能运行前请遵照系统说明).
-4. 如果你满意的话,可以将本软件复制到Application文件夹.
+ (由于 macOS 的安全策略,在真正能运行前请遵照系统说明).
+4. 如果你满意的话,可以将本软件复制到 Application 文件夹.
#### Debian/Ubuntu/CentOS
1. 安装 gnupg (如果你已经安装了请跳过)
- For Debian/Ubuntu
- ```shell
- $ sudo apt update
- $ sudo apt install gpg
- ```
+ ```shell
+ $ sudo apt update
+ $ sudo apt install gpg
+ ```
- For CentOS
- ```shell
- $ sudo yum install gnupg
- ```
+ ```shell
+ $ sudo yum install gnupg
+ ```
2. [下载 GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Linux edition from the latest release
-3. 解压 gpgfrontend-ubuntu-16.04-*******.zip
- - `ubuntu-16.04` 说明ubuntu 16.04及其同时期与后来的Linux发行版都可以正常运行。
-4. 赋予 `GpgFrontend-***.AppImage` 执行权限
+3. 赋予 `GpgFrontend-***.AppImage` 执行权限
```shell
$ chmod u+x ./GpgFrontend-***.AppImage
```
-5. 双击运行 `GpgFrontend-***.AppImage`.
+4. 双击运行 `GpgFrontend-***.AppImage`.
## 文档
-如果你想获取更多信息,请阅读 [文档](https://saturneric.github.io/GpgFrontend/index.html#/).
+如果你想获取更多信息,请阅读 [文档](https://gpgfrontend.pub/#/overview).
## 开发宗旨
-GpgFrontend 项目继承自一个相对成熟但未维护的 [gpg4usb](https://www.gpg4usb.org/) 项目。
-它继承了 gpg4usb 稳定、易用、小巧、免安装的特点。
+GpgFrontend 项目继承自一个相对成熟但未维护的 [gpg4usb](https://www.gpg4usb.org/) 项目。 它继承了 gpg4usb 稳定、易用、小巧、免安装的特点。
-GpgFrontend 未来会增加更多功能,提高GPG在端到端传输中的易用性并缩短密文长度。同时,新功能的加入不影响旧的基础功能。
-我个人的力量总是有限的。 GpgFrontend 欢迎志愿者加入。你可以使用 GitHub 平台提交问题或提交pull request。
+GpgFrontend 未来会增加更多功能,提高 GPG 在端到端传输中的易用性并缩短密文长度。同时,新功能的加入不影响旧的基础功能。 我个人的力量总是有限的。 GpgFrontend 欢迎志愿者加入。你可以使用 GitHub
+平台提交问题或提交 pull request。
GpgFrontend 项目作为开源项目,也坚持使用开源代码和库。
## 构建方法
-构建软件的教程将很快发布。
+构建软件的教程将很快发布。你可以先查看本项目的 GitHub Action 文件。
## 联系
-如果你想单独与我联系,你可以发送电子邮件到 [[email protected]](mailto:[email protected])。
+如果你想与我私下联系,你可以发送电子邮件到 [[email protected]](mailto:[email protected])。
-### 做出贡献
+### 做出贡献或者报告问题
-欢迎!你可以通过 [提出issue](https://github.com/saturneric/GpgFrontend/issues/new) 或提交 PR来做出贡献。
+欢迎!你可以通过 [提出 issue](https://github.com/saturneric/GpgFrontend/issues/new) 或提交 PR 来做出贡献。
-### 维护者
+### 关于维护者
-[@Saturneric](https://github.com/saturneric).
+该项目的维护者是 [@Saturneric](https://github.com/saturneric).
## LOGO
@@ -157,16 +160,27 @@ GpgFrontend 项目作为开源项目,也坚持使用开源代码和库。
GpgFrontend 在 [GPLv3](COPYING) 许可证下。
+[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend?ref=badge_large)
+
+### 依赖
+
项目使用到了一些库和二进制文件,它们(可能)具有不同的许可证,请查看它们的主页获取更多信息。您也可以从那里获取相关信息。
-gpg4usb: https://www.gpg4usb.org/
+gnupg: https://gnupg.org/
-Gnupg: https://gnupg.org/
+gpg4usb: https://www.gpg4usb.org/
-QT: https://www.qt.io/
+QT 5.15.2(opensource): https://www.qt.io/
MSYS2: https://www.msys2.org/
mingw-w64: http://mingw-w64.org/doku.php
-本软件图标使用来自阿里巴巴矢量图标库的素材。免费库中的图标未注册为商标。不涉及版权问题。 \ No newline at end of file
+AppImage: https://appimage.org/
+
+rapidjson: https://github.com/Tencent/rapidjson
+
+Application
+Bundles: [Link](!https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1)
+
+本软件图标使用来自 [阿里巴巴矢量图标库](!https://www.iconfont.cn/) 的素材。免费库中的图标未注册为商标。不涉及版权问题。
diff --git a/gpgfrontend.qrc b/gpgfrontend.qrc
index fce9f6bc..71513dbd 100644
--- a/gpgfrontend.qrc
+++ b/gpgfrontend.qrc
@@ -55,5 +55,7 @@
<file alias="mimetypes/unknown.png">resource/icons/mimetypes/unknown.png</file>
<file alias="button_previous.png">resource/icons/button_previous.png</file>
<file alias="button_next.png">resource/icons/button_next.png</file>
+ <file alias="refresh.png">resource/icons/refresh.png</file>
+ <file alias="up.png">resource/icons/up.png</file>
</qresource>
</RCC>
diff --git a/include/GpgFrontend.h.in b/include/GpgFrontend.h.in
index de88bab2..555f4589 100644
--- a/include/GpgFrontend.h.in
+++ b/include/GpgFrontend.h.in
@@ -1,3 +1,27 @@
+/**
+ * This file is part of GPGFrontend.
+ *
+ * GPGFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ */
+
#ifndef GPGFRONTEND_H_IN
#define GPGFRONTEND_H_IN
@@ -23,22 +47,8 @@
#define RELEASE 0
#define DEBUG 1
-#define PROJECT_NAME "@PROJECT_NAME@"
-#define BUILD_VERSION "@BUILD_VERSION@"
-#define GIT_VERSION "@GIT_VERSION@"
#define OS_PLATFORM @OS_PLATFORM@
-#define BUILD_FLAG @BUILD_FLAG@
-
-#define VERSION_MAJOR @CMAKE_PROJECT_VERSION_MAJOR@
-#define VERSION_MINOR @CMAKE_PROJECT_VERSION_MINOR@
-#define VERSION_PATCH @CMAKE_PROJECT_VERSION_PATCH@
-
-#define BUILD_TIMESTAMP "@BUILD_TIMESTAMP@"
-
-#define GIT_BRANCH_NAME "@GIT_BRANCH_NAME@"
-#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@"
-
#if OS_PLATFORM == MACOS && BUILD_FLAG == RELEASE
# define RESOURCE_DIR(appDir) (appDir + "/../Resources/")
#elif OS_PLATFORM == LINUX && BUILD_FLAG == RELEASE
diff --git a/include/GpgFrontendBuildInfo.h b/include/GpgFrontendBuildInfo.h.in
index 6e07a8bc..1da57de9 100644
--- a/include/GpgFrontendBuildInfo.h
+++ b/include/GpgFrontendBuildInfo.h.in
@@ -25,20 +25,19 @@
#ifndef GPGFRONTEND_BUILD_INFO_H_IN
#define GPGFRONTEND_BUILD_INFO_H_IN
-#define VERSION_MAJOR 1
-#define VERSION_MINOR 2
-#define VERSION_PATCH 2
+#define VERSION_MAJOR @CMAKE_PROJECT_VERSION_MAJOR@
+#define VERSION_MINOR @CMAKE_PROJECT_VERSION_MINOR@
+#define VERSION_PATCH @CMAKE_PROJECT_VERSION_PATCH@
-#define GIT_BRANCH_NAME "develop"
-#define GIT_COMMIT_HASH "70053b17c76b010537a5c183621dc0c14e9e416e"
+#define GIT_BRANCH_NAME "@GIT_BRANCH_NAME@"
+#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@"
-#define PROJECT_NAME "GpgFrontend"
-#define BUILD_VERSION "1.2.2_Darwin-20.5.0_x86_64_Release"
-#define GIT_VERSION "develop_70053b17c76b010537a5c183621dc0c14e9e416e"
-#define OS_PLATFORM 1
+#define PROJECT_NAME "@PROJECT_NAME@"
+#define BUILD_VERSION "@BUILD_VERSION@"
+#define GIT_VERSION "@GIT_VERSION@"
-#define BUILD_FLAG 0
+#define BUILD_FLAG @BUILD_FLAG@
-#define BUILD_TIMESTAMP "2021-07-20 21:56:45"
+#define BUILD_TIMESTAMP "@BUILD_TIMESTAMP@"
#endif // GPGFRONTEND_BUILD_INFO_H_IN
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 418a56db..20f9a0b5 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -26,12 +26,11 @@
#define __GPGWIN_H__
#include "gpg/GpgConstants.h"
-#include "ui/widgets/Attachments.h"
#include "ui/KeyMgmt.h"
#include "ui/widgets/TextEdit.h"
#include "ui/FileEncryptionDialog.h"
#include "ui/SettingsDialog.h"
-#include "ui/AboutDialog.h"
+#include "ui/help/AboutDialog.h"
#include "ui/widgets/InfoBoardWidget.h"
#include "ui/FindWidget.h"
#include "ui/Wizard.h"
@@ -217,6 +216,11 @@ private slots:
void slotAbout();
/**
+ * @details Open check-update-tab in about-dialog.
+ */
+ void slotCheckUpdate();
+
+ /**
* @details Open File Opera Tab
*/
void slotOpenFileTab();
@@ -258,6 +262,11 @@ private slots:
*/
void slotSetRestartNeeded(bool needed);
+ /**
+ * @details called when need to upgrade.
+ */
+ void slotVersionUpgrade(const QString &currentVersion, const QString &latestVersion);
+
private:
/**
* @details Create actions for the main-menu and the context-menu of the keylist.
@@ -363,6 +372,7 @@ private:
QAction *zoomInAct; /** Action to zoom in */
QAction *zoomOutAct; /** Action to zoom out */
QAction *aboutAct; /** Action to open about dialog */
+ QAction *checkUpdateAct; /** Action to open about dialog */
QAction *fileEncryptAct; /** Action to open dialog for encrypting file */
QAction *fileDecryptAct; /** Action to open dialog for decrypting file */
QAction *fileSignAct; /** Action to open dialog for signing file */
@@ -382,11 +392,12 @@ private:
KeyList *mKeyList;
InfoBoardWidget *infoBoard;
- Attachments *mAttachments; /**< TODO */
- GpgME::GpgContext *mCtx; /**< TODO */
- KeyMgmt *keyMgmt; /**< TODO */
+ GpgME::GpgContext *mCtx;
+ KeyMgmt *keyMgmt;
KeyServerImportDialog *importDialog; /**< TODO */
+ QNetworkAccessManager *networkAccessManager;
+
bool attachmentDockCreated;
bool restartNeeded;
};
diff --git a/include/Mime.h b/include/Mime.h
deleted file mode 100644
index c86ac630..00000000
--- a/include/Mime.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-#ifndef __MIME_H__
-#define __MIME_H__
-
-#include <GpgFrontend.h>
-#include <utility>
-
-class HeadElem {
-public:
- QString name;
- QString value;
- QHash<QString, QString> params;
-
- /* QDataStream & operator<<(QDataStream& Stream, const HeadElem& H)
- {
- return Stream << H.name << " : " << H.value;
- }*/
-
-};
-
-class Header {
-public:
- QList<HeadElem> headElems;
-
- Header() = default;
-
- explicit Header(QList<HeadElem> heads) {
- headElems = std::move(heads);
- }
-
- [[maybe_unused]] void setHeader(QList<HeadElem> heads) {
- headElems = std::move(heads);
- }
-
- QString getValue(const QString &key) {
- foreach(HeadElem tmp, headElems) {
- //qDebug() << "gv: " << tmp.name << ":" << tmp.value;
- if (tmp.name == key)
- return tmp.value;
- }
- return "";
- }
-
- QHash<QString, QString> getParams(const QString &key) {
- foreach(HeadElem tmp, headElems) {
- //qDebug() << "gv: " << tmp.name << ":" << tmp.value;
- if (tmp.name == key)
- //return tmp.value;
- return tmp.params;
- }
- return *(new QHash<QString, QString>());
- }
-
- QString getParam(const QString &key, const QString &pKey) {
- foreach(HeadElem tmp, headElems) {
- //qDebug() << "gv: " << tmp.name << ":" << tmp.value;
- if (tmp.name == key)
- return tmp.params.value(pKey);
- }
- return "";
- }
-
-
-};
-
-class MimePart {
-public:
- Header header;
- QByteArray body;
-
-
-
- /* QDataStream & operator<<(QDataStream& Stream, const Part& P)
- {
- foreach(HeadElem tmp, header) {
- Stream << tmp << "\n";
- }
- return Stream;
- }*/
-};
-
-class Mime {
-
-public:
- explicit Mime(QByteArray *message); // Constructor
- ~Mime(); // Destructor
- static bool isMultipart(QByteArray *message);
-
- static bool isMime(const QByteArray *message);
-
- QList<MimePart> parts() {
- return mPartList;
- }
-
- void splitParts(QByteArray *message);
-
- static Header getHeader(const QByteArray *message);
-
- static Header parseHeader(QByteArray *header);
-
- static void quotedPrintableDecode(const QByteArray &in, QByteArray &out);
-
-private:
- QList<MimePart> mPartList;
-};
-
-#endif // __MIME_H__
diff --git a/include/gpg/GpgContext.h b/include/gpg/GpgContext.h
index a2812b4e..fc4d8692 100644
--- a/include/gpg/GpgContext.h
+++ b/include/gpg/GpgContext.h
@@ -71,7 +71,7 @@ namespace GpgME {
~GpgContext() override;
- bool isGood() const;
+ [[nodiscard]] bool isGood() const;
GpgImportInformation importKey(QByteArray inBuffer);
@@ -115,7 +115,7 @@ namespace GpgME {
gpg_error_t
sign(const QVector<GpgKey> &keys, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached = false,
- gpgme_sign_result_t* result = nullptr);
+ gpgme_sign_result_t *result = nullptr);
bool addUID(const GpgKey &key, const GpgUID &uid);
@@ -125,6 +125,8 @@ namespace GpgME {
bool setExpire(const GpgKey &key, const GpgSubKey *subkey, QDateTime *expires);
+ QProcess * generateRevokeCert(const GpgKey &key, const QString &outputFileName);
+
static bool checkIfKeyCanSign(const GpgKey &key);
static bool checkIfKeyCanCert(const GpgKey &key);
@@ -133,6 +135,7 @@ namespace GpgME {
static bool checkIfKeyCanEncr(const GpgKey &key);
+
/**
* @details If text contains PGP-message, put a linebreak before the message,
* so that gpgme can decrypt correctly
@@ -143,7 +146,7 @@ namespace GpgME {
GpgKey getKeyByFpr(const QString &fpr);
- const GpgKey & getKeyById(const QString &id);
+ const GpgKey &getKeyById(const QString &id);
static QString gpgErrString(gpgme_error_t err);
@@ -173,7 +176,7 @@ namespace GpgME {
void slotRefreshKeyList();
- void slotUpdateKeyList(const QString& key_id);
+ void slotUpdateKeyList(const QString &key_id);
private:
gpgme_ctx_t mCtx{};
@@ -204,11 +207,11 @@ namespace GpgME {
const char *passphrase_info,
int last_was_bad, int fd);
- void executeGpgCommand(const QStringList &arguments,
- QByteArray *stdOut,
- QByteArray *stdErr);
+ QProcess * executeGpgCommand(const QStringList &arguments,
+ QByteArray *stdOut,
+ QByteArray *stdErr, const std::function<void(QProcess *)> &interactFunc);
- QString gpgBin;
+ QString gpgExec;
QString gpgKeys;
};
} // namespace GpgME
diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h
new file mode 100644
index 00000000..98affe03
--- /dev/null
+++ b/include/rapidjson/allocators.h
@@ -0,0 +1,271 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ALLOCATORS_H_
+#define RAPIDJSON_ALLOCATORS_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocator
+
+/*! \class rapidjson::Allocator
+ \brief Concept for allocating, resizing and freeing memory block.
+
+ Note that Malloc() and Realloc() are non-static but Free() is static.
+
+ So if an allocator need to support Free(), it needs to put its pointer in
+ the header of memory block.
+
+\code
+concept Allocator {
+ static const bool kNeedFree; //!< Whether this allocator needs to call Free().
+
+ // Allocate a memory block.
+ // \param size of the memory block in bytes.
+ // \returns pointer to the memory block.
+ void* Malloc(size_t size);
+
+ // Resize a memory block.
+ // \param originalPtr The pointer to current memory block. Null pointer is permitted.
+ // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
+ // \param newSize the new size in bytes.
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
+
+ // Free a memory block.
+ // \param pointer to the memory block. Null pointer is permitted.
+ static void Free(void *ptr);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// CrtAllocator
+
+//! C-runtime library allocator.
+/*! This class is just wrapper for standard C library memory routines.
+ \note implements Allocator concept
+*/
+class CrtAllocator {
+public:
+ static const bool kNeedFree = true;
+ void* Malloc(size_t size) {
+ if (size) // behavior of malloc(0) is implementation defined.
+ return std::malloc(size);
+ else
+ return NULL; // standardize to returning NULL.
+ }
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+ (void)originalSize;
+ if (newSize == 0) {
+ std::free(originalPtr);
+ return NULL;
+ }
+ return std::realloc(originalPtr, newSize);
+ }
+ static void Free(void *ptr) { std::free(ptr); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryPoolAllocator
+
+//! Default memory allocator used by the parser and DOM.
+/*! This allocator allocate memory blocks from pre-allocated memory chunks.
+
+ It does not free memory blocks. And Realloc() only allocate new memory.
+
+ The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
+
+ User may also supply a buffer as the first chunk.
+
+ If the user-buffer is full then additional chunks are allocated by BaseAllocator.
+
+ The user-buffer is not deallocated by this allocator.
+
+ \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
+ \note implements Allocator concept
+*/
+template <typename BaseAllocator = CrtAllocator>
+class MemoryPoolAllocator {
+public:
+ static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
+
+ //! Constructor with chunkSize.
+ /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ }
+
+ //! Constructor with user-supplied buffer.
+ /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
+
+ The user buffer will not be deallocated when this allocator is destructed.
+
+ \param buffer User supplied buffer.
+ \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
+ \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ RAPIDJSON_ASSERT(buffer != 0);
+ RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
+ chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
+ chunkHead_->capacity = size - sizeof(ChunkHeader);
+ chunkHead_->size = 0;
+ chunkHead_->next = 0;
+ }
+
+ //! Destructor.
+ /*! This deallocates all memory chunks, excluding the user-supplied buffer.
+ */
+ ~MemoryPoolAllocator() {
+ Clear();
+ RAPIDJSON_DELETE(ownBaseAllocator_);
+ }
+
+ //! Deallocates all memory chunks, excluding the user-supplied buffer.
+ void Clear() {
+ while (chunkHead_ && chunkHead_ != userBuffer_) {
+ ChunkHeader* next = chunkHead_->next;
+ baseAllocator_->Free(chunkHead_);
+ chunkHead_ = next;
+ }
+ if (chunkHead_ && chunkHead_ == userBuffer_)
+ chunkHead_->size = 0; // Clear user buffer
+ }
+
+ //! Computes the total capacity of allocated memory chunks.
+ /*! \return total capacity in bytes.
+ */
+ size_t Capacity() const {
+ size_t capacity = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ capacity += c->capacity;
+ return capacity;
+ }
+
+ //! Computes the memory blocks allocated.
+ /*! \return total used bytes.
+ */
+ size_t Size() const {
+ size_t size = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ size += c->size;
+ return size;
+ }
+
+ //! Allocates a memory block. (concept Allocator)
+ void* Malloc(size_t size) {
+ if (!size)
+ return NULL;
+
+ size = RAPIDJSON_ALIGN(size);
+ if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
+ if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
+ return NULL;
+
+ void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
+ chunkHead_->size += size;
+ return buffer;
+ }
+
+ //! Resizes a memory block (concept Allocator)
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+ if (originalPtr == 0)
+ return Malloc(newSize);
+
+ if (newSize == 0)
+ return NULL;
+
+ originalSize = RAPIDJSON_ALIGN(originalSize);
+ newSize = RAPIDJSON_ALIGN(newSize);
+
+ // Do not shrink if new size is smaller than original
+ if (originalSize >= newSize)
+ return originalPtr;
+
+ // Simply expand it if it is the last allocation and there is sufficient space
+ if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
+ size_t increment = static_cast<size_t>(newSize - originalSize);
+ if (chunkHead_->size + increment <= chunkHead_->capacity) {
+ chunkHead_->size += increment;
+ return originalPtr;
+ }
+ }
+
+ // Realloc process: allocate and copy memory, do not free original buffer.
+ if (void* newBuffer = Malloc(newSize)) {
+ if (originalSize)
+ std::memcpy(newBuffer, originalPtr, originalSize);
+ return newBuffer;
+ }
+ else
+ return NULL;
+ }
+
+ //! Frees a memory block (concept Allocator)
+ static void Free(void *ptr) { (void)ptr; } // Do nothing
+
+private:
+ //! Copy constructor is not permitted.
+ MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
+ //! Copy assignment operator is not permitted.
+ MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
+
+ //! Creates a new chunk.
+ /*! \param capacity Capacity of the chunk in bytes.
+ \return true if success.
+ */
+ bool AddChunk(size_t capacity) {
+ if (!baseAllocator_)
+ ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
+ if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
+ chunk->capacity = capacity;
+ chunk->size = 0;
+ chunk->next = chunkHead_;
+ chunkHead_ = chunk;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
+
+ //! Chunk header for perpending to each chunk.
+ /*! Chunks are stored as a singly linked list.
+ */
+ struct ChunkHeader {
+ size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
+ size_t size; //!< Current size of allocated memory in bytes.
+ ChunkHeader *next; //!< Next chunk in the linked list.
+ };
+
+ ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
+ size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
+ void *userBuffer_; //!< User supplied buffer.
+ BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
+ BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h
new file mode 100644
index 00000000..e3e20dfb
--- /dev/null
+++ b/include/rapidjson/document.h
@@ -0,0 +1,2575 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_DOCUMENT_H_
+#define RAPIDJSON_DOCUMENT_H_
+
+/*! \file document.h */
+
+#include "reader.h"
+#include "internal/meta.h"
+#include "internal/strfunc.h"
+#include "memorystream.h"
+#include "encodedstream.h"
+#include <new> // placement new
+#include <limits>
+
+RAPIDJSON_DIAG_PUSH
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_OFF(effc++)
+#if __GNUC__ >= 6
+RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions
+#endif
+#endif // __GNUC__
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+#include <iterator> // std::iterator, std::random_access_iterator_tag
+#endif
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// Forward declaration.
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+template <typename Encoding, typename Allocator, typename StackAllocator>
+class GenericDocument;
+
+//! Name-value pair in a JSON object value.
+/*!
+ This class was internal to GenericValue. It used to be a inner struct.
+ But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
+ https://code.google.com/p/rapidjson/issues/detail?id=64
+*/
+template <typename Encoding, typename Allocator>
+struct GenericMember {
+ GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
+ GenericValue<Encoding, Allocator> value; //!< value of member.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericMemberIterator
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+
+//! (Constant) member iterator for a JSON object value
+/*!
+ \tparam Const Is this a constant iterator?
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+
+ This class implements a Random Access Iterator for GenericMember elements
+ of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
+
+ \note This iterator implementation is mainly intended to avoid implicit
+ conversions from iterator values to \c NULL,
+ e.g. from GenericValue::FindMember.
+
+ \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
+ pointer-based implementation, if your platform doesn't provide
+ the C++ <iterator> header.
+
+ \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
+ */
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator
+ : public std::iterator<std::random_access_iterator_tag
+ , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
+
+ friend class GenericValue<Encoding,Allocator>;
+ template <bool, typename, typename> friend class GenericMemberIterator;
+
+ typedef GenericMember<Encoding,Allocator> PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
+
+public:
+ //! Iterator type itself
+ typedef GenericMemberIterator Iterator;
+ //! Constant iterator type
+ typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
+ //! Non-constant iterator type
+ typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
+
+ //! Pointer to (const) GenericMember
+ typedef typename BaseType::pointer Pointer;
+ //! Reference to (const) GenericMember
+ typedef typename BaseType::reference Reference;
+ //! Signed integer type (e.g. \c ptrdiff_t)
+ typedef typename BaseType::difference_type DifferenceType;
+
+ //! Default constructor (singular value)
+ /*! Creates an iterator pointing to no element.
+ \note All operations, except for comparisons, are undefined on such values.
+ */
+ GenericMemberIterator() : ptr_() {}
+
+ //! Iterator conversions to more const
+ /*!
+ \param it (Non-const) iterator to copy from
+
+ Allows the creation of an iterator from another GenericMemberIterator
+ that is "less const". Especially, creating a non-constant iterator
+ from a constant iterator are disabled:
+ \li const -> non-const (not ok)
+ \li const -> const (ok)
+ \li non-const -> const (ok)
+ \li non-const -> non-const (ok)
+
+ \note If the \c Const template parameter is already \c false, this
+ constructor effectively defines a regular copy-constructor.
+ Otherwise, the copy constructor is implicitly defined.
+ */
+ GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
+ Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }
+
+ //! @name stepping
+ //@{
+ Iterator& operator++(){ ++ptr_; return *this; }
+ Iterator& operator--(){ --ptr_; return *this; }
+ Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
+ Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
+ //@}
+
+ //! @name increment/decrement
+ //@{
+ Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
+ Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
+
+ Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
+ Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
+ //@}
+
+ //! @name relations
+ //@{
+ bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
+ bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
+ bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
+ bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
+ bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
+ bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
+ //@}
+
+ //! @name dereference
+ //@{
+ Reference operator*() const { return *ptr_; }
+ Pointer operator->() const { return ptr_; }
+ Reference operator[](DifferenceType n) const { return ptr_[n]; }
+ //@}
+
+ //! Distance
+ DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
+
+private:
+ //! Internal constructor from plain pointer
+ explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
+
+ Pointer ptr_; //!< raw pointer
+};
+
+#else // RAPIDJSON_NOMEMBERITERATORCLASS
+
+// class-based member iterator implementation disabled, use plain pointers
+
+template <bool Const, typename Encoding, typename Allocator>
+struct GenericMemberIterator;
+
+//! non-const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<false,Encoding,Allocator> {
+ //! use plain pointer as iterator type
+ typedef GenericMember<Encoding,Allocator>* Iterator;
+};
+//! const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<true,Encoding,Allocator> {
+ //! use plain const pointer as iterator type
+ typedef const GenericMember<Encoding,Allocator>* Iterator;
+};
+
+#endif // RAPIDJSON_NOMEMBERITERATORCLASS
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericStringRef
+
+//! Reference to a constant string (not taking a copy)
+/*!
+ \tparam CharType character type of the string
+
+ This helper class is used to automatically infer constant string
+ references for string literals, especially from \c const \b (!)
+ character arrays.
+
+ The main use is for creating JSON string values without copying the
+ source string via an \ref Allocator. This requires that the referenced
+ string pointers have a sufficient lifetime, which exceeds the lifetime
+ of the associated GenericValue.
+
+ \b Example
+ \code
+ Value v("foo"); // ok, no need to copy & calculate length
+ const char foo[] = "foo";
+ v.SetString(foo); // ok
+
+ const char* bar = foo;
+ // Value x(bar); // not ok, can't rely on bar's lifetime
+ Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
+ Value y(StringRef(bar, 3)); // ok, explicitly pass length
+ \endcode
+
+ \see StringRef, GenericValue::SetString
+*/
+template<typename CharType>
+struct GenericStringRef {
+ typedef CharType Ch; //!< character type of the string
+
+ //! Create string reference from \c const character array
+#ifndef __clang__ // -Wdocumentation
+ /*!
+ This constructor implicitly creates a constant string reference from
+ a \c const character array. It has better performance than
+ \ref StringRef(const CharType*) by inferring the string \ref length
+ from the array length, and also supports strings containing null
+ characters.
+
+ \tparam N length of the string, automatically inferred
+
+ \param str Constant character array, lifetime assumed to be longer
+ than the use of the string in e.g. a GenericValue
+
+ \post \ref s == str
+
+ \note Constant complexity.
+ \note There is a hidden, private overload to disallow references to
+ non-const character arrays to be created via this constructor.
+ By this, e.g. function-scope arrays used to be filled via
+ \c snprintf are excluded from consideration.
+ In such cases, the referenced string should be \b copied to the
+ GenericValue instead.
+ */
+#endif
+ template<SizeType N>
+ GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
+ : s(str), length(N-1) {}
+
+ //! Explicitly create string reference from \c const character pointer
+#ifndef __clang__ // -Wdocumentation
+ /*!
+ This constructor can be used to \b explicitly create a reference to
+ a constant string pointer.
+
+ \see StringRef(const CharType*)
+
+ \param str Constant character pointer, lifetime assumed to be longer
+ than the use of the string in e.g. a GenericValue
+
+ \post \ref s == str
+
+ \note There is a hidden, private overload to disallow references to
+ non-const character arrays to be created via this constructor.
+ By this, e.g. function-scope arrays used to be filled via
+ \c snprintf are excluded from consideration.
+ In such cases, the referenced string should be \b copied to the
+ GenericValue instead.
+ */
+#endif
+ explicit GenericStringRef(const CharType* str)
+ : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); }
+
+ //! Create constant string reference from pointer and length
+#ifndef __clang__ // -Wdocumentation
+ /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \param len length of the string, excluding the trailing NULL terminator
+
+ \post \ref s == str && \ref length == len
+ \note Constant complexity.
+ */
+#endif
+ GenericStringRef(const CharType* str, SizeType len)
+ : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); }
+
+ GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
+
+ GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
+
+ //! implicit conversion to plain CharType pointer
+ operator const Ch *() const { return s; }
+
+ const Ch* const s; //!< plain CharType pointer
+ const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
+
+private:
+ //! Disallow construction from non-const array
+ template<SizeType N>
+ GenericStringRef(CharType (&str)[N]) /* = delete */;
+};
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal". This function
+ can be used to avoid copying a character string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+ \tparam CharType Character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+
+ \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str) {
+ return GenericStringRef<CharType>(str, internal::StrLen(str));
+}
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal". This function
+ can be used to avoid copying a character string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+
+ This version has better performance with supplied length, and also
+ supports string containing null characters.
+
+ \tparam CharType character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \param length The length of source string.
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
+ return GenericStringRef<CharType>(str, SizeType(length));
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+//! Mark a string object as constant string
+/*! Mark a string object (e.g. \c std::string) as a "string literal".
+ This function can be used to avoid copying a string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+
+ \tparam CharType character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
+ return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue type traits
+namespace internal {
+
+template <typename T, typename Encoding = void, typename Allocator = void>
+struct IsGenericValueImpl : FalseType {};
+
+// select candidates according to nested encoding and allocator types
+template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
+ : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
+
+// helper to match arbitrary GenericValue instantiations, including derived classes
+template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// TypeHelper
+
+namespace internal {
+
+template <typename ValueType, typename T>
+struct TypeHelper {};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, bool> {
+ static bool Is(const ValueType& v) { return v.IsBool(); }
+ static bool Get(const ValueType& v) { return v.GetBool(); }
+ static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }
+ static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, int> {
+ static bool Is(const ValueType& v) { return v.IsInt(); }
+ static int Get(const ValueType& v) { return v.GetInt(); }
+ static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }
+ static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, unsigned> {
+ static bool Is(const ValueType& v) { return v.IsUint(); }
+ static unsigned Get(const ValueType& v) { return v.GetUint(); }
+ static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); }
+ static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, int64_t> {
+ static bool Is(const ValueType& v) { return v.IsInt64(); }
+ static int64_t Get(const ValueType& v) { return v.GetInt64(); }
+ static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); }
+ static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, uint64_t> {
+ static bool Is(const ValueType& v) { return v.IsUint64(); }
+ static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
+ static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); }
+ static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, double> {
+ static bool Is(const ValueType& v) { return v.IsDouble(); }
+ static double Get(const ValueType& v) { return v.GetDouble(); }
+ static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); }
+ static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, float> {
+ static bool Is(const ValueType& v) { return v.IsFloat(); }
+ static float Get(const ValueType& v) { return v.GetFloat(); }
+ static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }
+ static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, const typename ValueType::Ch*> {
+ typedef const typename ValueType::Ch* StringType;
+ static bool Is(const ValueType& v) { return v.IsString(); }
+ static StringType Get(const ValueType& v) { return v.GetString(); }
+ static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); }
+ static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
+};
+
+#if RAPIDJSON_HAS_STDSTRING
+template<typename ValueType>
+struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
+ typedef std::basic_string<typename ValueType::Ch> StringType;
+ static bool Is(const ValueType& v) { return v.IsString(); }
+ static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); }
+ static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
+};
+#endif
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::Array> {
+ typedef typename ValueType::Array ArrayType;
+ static bool Is(const ValueType& v) { return v.IsArray(); }
+ static ArrayType Get(ValueType& v) { return v.GetArray(); }
+ static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }
+ static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::ConstArray> {
+ typedef typename ValueType::ConstArray ArrayType;
+ static bool Is(const ValueType& v) { return v.IsArray(); }
+ static ArrayType Get(const ValueType& v) { return v.GetArray(); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::Object> {
+ typedef typename ValueType::Object ObjectType;
+ static bool Is(const ValueType& v) { return v.IsObject(); }
+ static ObjectType Get(ValueType& v) { return v.GetObject(); }
+ static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
+ static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::ConstObject> {
+ typedef typename ValueType::ConstObject ObjectType;
+ static bool Is(const ValueType& v) { return v.IsObject(); }
+ static ObjectType Get(const ValueType& v) { return v.GetObject(); }
+};
+
+} // namespace internal
+
+// Forward declarations
+template <bool, typename> class GenericArray;
+template <bool, typename> class GenericObject;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue
+
+//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
+/*!
+ A JSON value can be one of 7 types. This class is a variant type supporting
+ these types.
+
+ Use the Value if UTF8 and default allocator
+
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
+class GenericValue {
+public:
+ //! Name-value pair in an object.
+ typedef GenericMember<Encoding, Allocator> Member;
+ typedef Encoding EncodingType; //!< Encoding type from template parameter.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
+ typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
+ typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
+ typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
+ typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself.
+ typedef GenericArray<false, ValueType> Array;
+ typedef GenericArray<true, ValueType> ConstArray;
+ typedef GenericObject<false, ValueType> Object;
+ typedef GenericObject<true, ValueType> ConstObject;
+
+ //!@name Constructors and destructor.
+ //@{
+
+ //! Default constructor creates a null value.
+ GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
+ rhs.data_.f.flags = kNullFlag; // give up contents
+ }
+#endif
+
+private:
+ //! Copy constructor is not permitted.
+ GenericValue(const GenericValue& rhs);
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Moving from a GenericDocument is not permitted.
+ template <typename StackAllocator>
+ GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
+
+ //! Move assignment from a GenericDocument is not permitted.
+ template <typename StackAllocator>
+ GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
+#endif
+
+public:
+
+ //! Constructor with JSON value type.
+ /*! This creates a Value of specified type with default content.
+ \param type Type of the value.
+ \note Default content for number is zero.
+ */
+ explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
+ static const uint16_t defaultFlags[7] = {
+ kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
+ kNumberAnyFlag
+ };
+ RAPIDJSON_ASSERT(type <= kNumberType);
+ data_.f.flags = defaultFlags[type];
+
+ // Use ShortString to store empty string.
+ if (type == kStringType)
+ data_.ss.SetLength(0);
+ }
+
+ //! Explicit copy constructor (with allocator)
+ /*! Creates a copy of a Value by using the given Allocator
+ \tparam SourceAllocator allocator of \c rhs
+ \param rhs Value to copy from (read-only)
+ \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
+ \see CopyFrom()
+ */
+ template< typename SourceAllocator >
+ GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
+
+ //! Constructor for boolean value.
+ /*! \param b Boolean value
+ \note This constructor is limited to \em real boolean values and rejects
+ implicitly converted types like arbitrary pointers. Use an explicit cast
+ to \c bool, if you want to construct a boolean JSON value in such cases.
+ */
+#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
+ template <typename T>
+ explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472
+#else
+ explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
+#endif
+ : data_() {
+ // safe-guard against failing SFINAE
+ RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
+ data_.f.flags = b ? kTrueFlag : kFalseFlag;
+ }
+
+ //! Constructor for int value.
+ explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
+ data_.n.i64 = i;
+ data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;
+ }
+
+ //! Constructor for unsigned value.
+ explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
+ data_.n.u64 = u;
+ data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
+ }
+
+ //! Constructor for int64_t value.
+ explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
+ data_.n.i64 = i64;
+ data_.f.flags = kNumberInt64Flag;
+ if (i64 >= 0) {
+ data_.f.flags |= kNumberUint64Flag;
+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ data_.f.flags |= kUintFlag;
+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ data_.f.flags |= kIntFlag;
+ }
+ else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ data_.f.flags |= kIntFlag;
+ }
+
+ //! Constructor for uint64_t value.
+ explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
+ data_.n.u64 = u64;
+ data_.f.flags = kNumberUint64Flag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
+ data_.f.flags |= kInt64Flag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ data_.f.flags |= kUintFlag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ data_.f.flags |= kIntFlag;
+ }
+
+ //! Constructor for double value.
+ explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Constructor for copy-string from a string object (i.e. do make a copy of string)
+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
+#endif
+
+ //! Constructor for Array.
+ /*!
+ \param a An array obtained by \c GetArray().
+ \note \c Array is always pass-by-value.
+ \note the source array is moved into this value and the sourec array becomes empty.
+ */
+ GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
+ a.value_.data_ = Data();
+ a.value_.data_.f.flags = kArrayFlag;
+ }
+
+ //! Constructor for Object.
+ /*!
+ \param o An object obtained by \c GetObject().
+ \note \c Object is always pass-by-value.
+ \note the source object is moved into this value and the sourec object becomes empty.
+ */
+ GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
+ o.value_.data_ = Data();
+ o.value_.data_.f.flags = kObjectFlag;
+ }
+
+ //! Destructor.
+ /*! Need to destruct elements of array, members of object, or copy-string.
+ */
+ ~GenericValue() {
+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
+ switch(data_.f.flags) {
+ case kArrayFlag:
+ {
+ GenericValue* e = GetElementsPointer();
+ for (GenericValue* v = e; v != e + data_.a.size; ++v)
+ v->~GenericValue();
+ Allocator::Free(e);
+ }
+ break;
+
+ case kObjectFlag:
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+ m->~Member();
+ Allocator::Free(GetMembersPointer());
+ break;
+
+ case kCopyStringFlag:
+ Allocator::Free(const_cast<Ch*>(GetStringPointer()));
+ break;
+
+ default:
+ break; // Do nothing for other types.
+ }
+ }
+ }
+
+ //@}
+
+ //!@name Assignment operators
+ //@{
+
+ //! Assignment with move semantics.
+ /*! \param rhs Source of the assignment. It will become a null value after assignment.
+ */
+ GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_ASSERT(this != &rhs);
+ this->~GenericValue();
+ RawAssign(rhs);
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
+ return *this = rhs.Move();
+ }
+#endif
+
+ //! Assignment of constant string reference (no copy)
+ /*! \param str Constant string reference to be assigned
+ \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
+ \see GenericStringRef, operator=(T)
+ */
+ GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
+ GenericValue s(str);
+ return *this = s;
+ }
+
+ //! Assignment with primitive types.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param value The value to be assigned.
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref SetString(const Ch*, Allocator&) (for copying) or
+ \ref StringRef() (to explicitly mark the pointer as constant) instead.
+ All other pointer types would implicitly convert to \c bool,
+ use \ref SetBool() instead.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
+ operator=(T value) {
+ GenericValue v(value);
+ return *this = v;
+ }
+
+ //! Deep-copy assignment from Value
+ /*! Assigns a \b copy of the Value to the current Value object
+ \tparam SourceAllocator Allocator type of \c rhs
+ \param rhs Value to copy from (read-only)
+ \param allocator Allocator to use for copying
+ */
+ template <typename SourceAllocator>
+ GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
+ RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
+ this->~GenericValue();
+ new (this) GenericValue(rhs, allocator);
+ return *this;
+ }
+
+ //! Exchange the contents of this value with those of other.
+ /*!
+ \param other Another value.
+ \note Constant complexity.
+ */
+ GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
+ GenericValue temp;
+ temp.RawAssign(*this);
+ RawAssign(other);
+ other.RawAssign(temp);
+ return *this;
+ }
+
+ //! free-standing swap function helper
+ /*!
+ Helper function to enable support for common swap implementation pattern based on \c std::swap:
+ \code
+ void swap(MyClass& a, MyClass& b) {
+ using std::swap;
+ swap(a.value, b.value);
+ // ...
+ }
+ \endcode
+ \see Swap()
+ */
+ friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
+
+ //! Prepare Value for move semantics
+ /*! \return *this */
+ GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
+ //@}
+
+ //!@name Equal-to and not-equal-to operators
+ //@{
+ //! Equal-to operator
+ /*!
+ \note If an object contains duplicated named member, comparing equality with any object is always \c false.
+ \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
+ */
+ template <typename SourceAllocator>
+ bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+ typedef GenericValue<Encoding, SourceAllocator> RhsType;
+ if (GetType() != rhs.GetType())
+ return false;
+
+ switch (GetType()) {
+ case kObjectType: // Warning: O(n^2) inner-loop
+ if (data_.o.size != rhs.data_.o.size)
+ return false;
+ for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
+ typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
+ if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
+ return false;
+ }
+ return true;
+
+ case kArrayType:
+ if (data_.a.size != rhs.data_.a.size)
+ return false;
+ for (SizeType i = 0; i < data_.a.size; i++)
+ if ((*this)[i] != rhs[i])
+ return false;
+ return true;
+
+ case kStringType:
+ return StringEqual(rhs);
+
+ case kNumberType:
+ if (IsDouble() || rhs.IsDouble()) {
+ double a = GetDouble(); // May convert from integer to double.
+ double b = rhs.GetDouble(); // Ditto
+ return a >= b && a <= b; // Prevent -Wfloat-equal
+ }
+ else
+ return data_.n.u64 == rhs.data_.n.u64;
+
+ default:
+ return true;
+ }
+ }
+
+ //! Equal-to operator with const C-string pointer
+ bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Equal-to operator with string object
+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
+#endif
+
+ //! Equal-to operator with primitive types
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
+ */
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
+
+ //! Not-equal-to operator
+ /*! \return !(*this == rhs)
+ */
+ template <typename SourceAllocator>
+ bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
+
+ //! Not-equal-to operator with const C-string pointer
+ bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
+
+ //! Not-equal-to operator with arbitrary types
+ /*! \return !(*this == rhs)
+ */
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
+
+ //! Equal-to operator with arbitrary types (symmetric version)
+ /*! \return (rhs == lhs)
+ */
+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
+
+ //! Not-Equal-to operator with arbitrary types (symmetric version)
+ /*! \return !(rhs == lhs)
+ */
+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
+ //@}
+
+ //!@name Type
+ //@{
+
+ Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); }
+ bool IsNull() const { return data_.f.flags == kNullFlag; }
+ bool IsFalse() const { return data_.f.flags == kFalseFlag; }
+ bool IsTrue() const { return data_.f.flags == kTrueFlag; }
+ bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; }
+ bool IsObject() const { return data_.f.flags == kObjectFlag; }
+ bool IsArray() const { return data_.f.flags == kArrayFlag; }
+ bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
+ bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; }
+ bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; }
+ bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; }
+ bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
+ bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
+ bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
+
+ // Checks whether a number can be losslessly converted to a double.
+ bool IsLosslessDouble() const {
+ if (!IsNumber()) return false;
+ if (IsUint64()) {
+ uint64_t u = GetUint64();
+ volatile double d = static_cast<double>(u);
+ return (d >= 0.0)
+ && (d < static_cast<double>(std::numeric_limits<uint64_t>::max()))
+ && (u == static_cast<uint64_t>(d));
+ }
+ if (IsInt64()) {
+ int64_t i = GetInt64();
+ volatile double d = static_cast<double>(i);
+ return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()))
+ && (d < static_cast<double>(std::numeric_limits<int64_t>::max()))
+ && (i == static_cast<int64_t>(d));
+ }
+ return true; // double, int, uint are always lossless
+ }
+
+ // Checks whether a number is a float (possible lossy).
+ bool IsFloat() const {
+ if ((data_.f.flags & kDoubleFlag) == 0)
+ return false;
+ double d = GetDouble();
+ return d >= -3.4028234e38 && d <= 3.4028234e38;
+ }
+ // Checks whether a number can be losslessly converted to a float.
+ bool IsLosslessFloat() const {
+ if (!IsNumber()) return false;
+ double a = GetDouble();
+ if (a < static_cast<double>(-std::numeric_limits<float>::max())
+ || a > static_cast<double>(std::numeric_limits<float>::max()))
+ return false;
+ double b = static_cast<double>(static_cast<float>(a));
+ return a >= b && a <= b; // Prevent -Wfloat-equal
+ }
+
+ //@}
+
+ //!@name Null
+ //@{
+
+ GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
+
+ //@}
+
+ //!@name Bool
+ //@{
+
+ bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
+ //!< Set boolean value
+ /*! \post IsBool() == true */
+ GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
+
+ //@}
+
+ //!@name Object
+ //@{
+
+ //! Set this value as an empty object.
+ /*! \post IsObject() == true */
+ GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
+
+ //! Get the number of members in the object.
+ SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
+
+ //! Check whether the object is empty.
+ bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
+
+ //! Get a value from an object associated with the name.
+ /*! \pre IsObject() == true
+ \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
+ \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
+ Since 0.2, if the name is not correct, it will assert.
+ If user is unsure whether a member exists, user should use HasMember() first.
+ A better approach is to use FindMember().
+ \note Linear time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
+ GenericValue n(StringRef(name));
+ return (*this)[n];
+ }
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+ //! Get a value from an object associated with the name.
+ /*! \pre IsObject() == true
+ \tparam SourceAllocator Allocator of the \c name value
+
+ \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
+ And it can also handle strings with embedded null characters.
+
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator member = FindMember(name);
+ if (member != MemberEnd())
+ return member->value;
+ else {
+ RAPIDJSON_ASSERT(false); // see above note
+
+ // This will generate -Wexit-time-destructors in clang
+ // static GenericValue NullValue;
+ // return NullValue;
+
+ // Use static buffer and placement-new to prevent destruction
+ static char buffer[sizeof(GenericValue)];
+ return *new (buffer) GenericValue();
+ }
+ }
+ template <typename SourceAllocator>
+ const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Get a value from an object associated with name (string object).
+ GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
+ const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
+#endif
+
+ //! Const member iterator
+ /*! \pre IsObject() == true */
+ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }
+ //! Const \em past-the-end member iterator
+ /*! \pre IsObject() == true */
+ ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }
+ //! Member iterator
+ /*! \pre IsObject() == true */
+ MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
+ //! \em Past-the-end member iterator
+ /*! \pre IsObject() == true */
+ MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
+
+ //! Check whether a member exists in the object.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Check whether a member exists in the object with string object.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
+#endif
+
+ //! Check whether a member exists in the object with GenericValue name.
+ /*!
+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
+
+ //! Find member by name.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+
+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+ the requested member doesn't exist. For consistency with e.g.
+ \c std::map, this has been changed to MemberEnd() now.
+ \note Linear time complexity.
+ */
+ MemberIterator FindMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return FindMember(n);
+ }
+
+ ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+ //! Find member by name.
+ /*!
+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+
+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+ the requested member doesn't exist. For consistency with e.g.
+ \c std::map, this has been changed to MemberEnd() now.
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+ MemberIterator member = MemberBegin();
+ for ( ; member != MemberEnd(); ++member)
+ if (name.StringEqual(member->name))
+ break;
+ return member;
+ }
+ template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Find member by string object name.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+ */
+ MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); }
+ ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); }
+#endif
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note The ownership of \c name and \c value will be transferred to this object on success.
+ \pre IsObject() && name.IsString()
+ \post name.IsNull() && value.IsNull()
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+
+ ObjectData& o = data_.o;
+ if (o.size >= o.capacity) {
+ if (o.capacity == 0) {
+ o.capacity = kDefaultObjectCapacity;
+ SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))));
+ }
+ else {
+ SizeType oldCapacity = o.capacity;
+ o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
+ SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member))));
+ }
+ }
+ Member* members = GetMembersPointer();
+ members[o.size].name.RawAssign(name);
+ members[o.size].value.RawAssign(value);
+ o.size++;
+ return *this;
+ }
+
+ //! Add a constant string value as member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Add a string object as member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
+ GenericValue v(value, allocator);
+ return AddMember(name, v, allocator);
+ }
+#endif
+
+ //! Add any primitive value as member (name-value pair) to the object.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param name A string value as name of member.
+ \param value Value of primitive type \c T as value of member
+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+ AddMember(StringRefType, StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized Constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ AddMember(GenericValue& name, T value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A constant string reference as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note The ownership of \c value will be transferred to this object on success.
+ \pre IsObject()
+ \post value.IsNull()
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+
+ //! Add a constant string value as member (name-value pair) to the object.
+ /*! \param name A constant string reference as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+ //! Add any primitive value as member (name-value pair) to the object.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param name A constant string reference as name of member.
+ \param value Value of primitive type \c T as value of member
+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+ AddMember(StringRefType, StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized Constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ AddMember(StringRefType name, T value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+
+ //! Remove all members in the object.
+ /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
+ \note Linear time complexity.
+ */
+ void RemoveAllMembers() {
+ RAPIDJSON_ASSERT(IsObject());
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+ m->~Member();
+ data_.o.size = 0;
+ }
+
+ //! Remove a member in object by its name.
+ /*! \param name Name of member to be removed.
+ \return Whether the member existed.
+ \note This function may reorder the object members. Use \ref
+ EraseMember(ConstMemberIterator) if you need to preserve the
+ relative order of the remaining members.
+ \note Linear time complexity.
+ */
+ bool RemoveMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return RemoveMember(n);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
+#endif
+
+ template <typename SourceAllocator>
+ bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator m = FindMember(name);
+ if (m != MemberEnd()) {
+ RemoveMember(m);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //! Remove a member in object by iterator.
+ /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
+ \return the new iterator after removal.
+ \note This function may reorder the object members. Use \ref
+ EraseMember(ConstMemberIterator) if you need to preserve the
+ relative order of the remaining members.
+ \note Constant time complexity.
+ */
+ MemberIterator RemoveMember(MemberIterator m) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(GetMembersPointer() != 0);
+ RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
+
+ MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
+ if (data_.o.size > 1 && m != last)
+ *m = *last; // Move the last one to this place
+ else
+ m->~Member(); // Only one left, just destroy
+ --data_.o.size;
+ return m;
+ }
+
+ //! Remove a member from an object by iterator.
+ /*! \param pos iterator to the member to remove
+ \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
+ \return Iterator following the removed element.
+ If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
+ \note This function preserves the relative order of the remaining object
+ members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
+ \note Linear time complexity.
+ */
+ MemberIterator EraseMember(ConstMemberIterator pos) {
+ return EraseMember(pos, pos +1);
+ }
+
+ //! Remove members in the range [first, last) from an object.
+ /*! \param first iterator to the first member to remove
+ \param last iterator following the last member to remove
+ \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
+ \return Iterator following the last removed element.
+ \note This function preserves the relative order of the remaining object
+ members.
+ \note Linear time complexity.
+ */
+ MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(GetMembersPointer() != 0);
+ RAPIDJSON_ASSERT(first >= MemberBegin());
+ RAPIDJSON_ASSERT(first <= last);
+ RAPIDJSON_ASSERT(last <= MemberEnd());
+
+ MemberIterator pos = MemberBegin() + (first - MemberBegin());
+ for (MemberIterator itr = pos; itr != last; ++itr)
+ itr->~Member();
+ std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
+ data_.o.size -= static_cast<SizeType>(last - first);
+ return pos;
+ }
+
+ //! Erase a member in object by its name.
+ /*! \param name Name of member to be removed.
+ \return Whether the member existed.
+ \note Linear time complexity.
+ */
+ bool EraseMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return EraseMember(n);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
+#endif
+
+ template <typename SourceAllocator>
+ bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator m = FindMember(name);
+ if (m != MemberEnd()) {
+ EraseMember(m);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
+ ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
+
+ //@}
+
+ //!@name Array
+ //@{
+
+ //! Set this value as an empty array.
+ /*! \post IsArray == true */
+ GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
+
+ //! Get the number of elements in array.
+ SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
+
+ //! Get the capacity of array.
+ SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
+
+ //! Check whether the array is empty.
+ bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
+
+ //! Remove all elements in the array.
+ /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
+ \note Linear time complexity.
+ */
+ void Clear() {
+ RAPIDJSON_ASSERT(IsArray());
+ GenericValue* e = GetElementsPointer();
+ for (GenericValue* v = e; v != e + data_.a.size; ++v)
+ v->~GenericValue();
+ data_.a.size = 0;
+ }
+
+ //! Get an element from array by index.
+ /*! \pre IsArray() == true
+ \param index Zero-based index of element.
+ \see operator[](T*)
+ */
+ GenericValue& operator[](SizeType index) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(index < data_.a.size);
+ return GetElementsPointer()[index];
+ }
+ const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
+
+ //! Element iterator
+ /*! \pre IsArray() == true */
+ ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }
+ //! \em Past-the-end element iterator
+ /*! \pre IsArray() == true */
+ ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }
+ //! Constant element iterator
+ /*! \pre IsArray() == true */
+ ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
+ //! Constant \em past-the-end element iterator
+ /*! \pre IsArray() == true */
+ ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
+
+ //! Request the array to have enough capacity to store elements.
+ /*! \param newCapacity The capacity that the array at least need to have.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note Linear time complexity.
+ */
+ GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (newCapacity > data_.a.capacity) {
+ SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));
+ data_.a.capacity = newCapacity;
+ }
+ return *this;
+ }
+
+ //! Append a GenericValue at the end of the array.
+ /*! \param value Value to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \post value.IsNull() == true
+ \return The value itself for fluent API.
+ \note The ownership of \c value will be transferred to this array on success.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ \note Amortized constant time complexity.
+ */
+ GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (data_.a.size >= data_.a.capacity)
+ Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
+ GetElementsPointer()[data_.a.size++].RawAssign(value);
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
+ return PushBack(value, allocator);
+ }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+ //! Append a constant string reference at the end of the array.
+ /*! \param value Constant string reference to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \return The value itself for fluent API.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ \note Amortized constant time complexity.
+ \see GenericStringRef
+ */
+ GenericValue& PushBack(StringRefType value, Allocator& allocator) {
+ return (*this).template PushBack<StringRefType>(value, allocator);
+ }
+
+ //! Append a primitive value at the end of the array.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param value Value of primitive type T to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \return The value itself for fluent API.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref PushBack(GenericValue&, Allocator&) or \ref
+ PushBack(StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ PushBack(T value, Allocator& allocator) {
+ GenericValue v(value);
+ return PushBack(v, allocator);
+ }
+
+ //! Remove the last element in the array.
+ /*!
+ \note Constant time complexity.
+ */
+ GenericValue& PopBack() {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(!Empty());
+ GetElementsPointer()[--data_.a.size].~GenericValue();
+ return *this;
+ }
+
+ //! Remove an element of array by iterator.
+ /*!
+ \param pos iterator to the element to remove
+ \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
+ \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
+ \note Linear time complexity.
+ */
+ ValueIterator Erase(ConstValueIterator pos) {
+ return Erase(pos, pos + 1);
+ }
+
+ //! Remove elements in the range [first, last) of the array.
+ /*!
+ \param first iterator to the first element to remove
+ \param last iterator following the last element to remove
+ \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
+ \return Iterator following the last removed element.
+ \note Linear time complexity.
+ */
+ ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(data_.a.size > 0);
+ RAPIDJSON_ASSERT(GetElementsPointer() != 0);
+ RAPIDJSON_ASSERT(first >= Begin());
+ RAPIDJSON_ASSERT(first <= last);
+ RAPIDJSON_ASSERT(last <= End());
+ ValueIterator pos = Begin() + (first - Begin());
+ for (ValueIterator itr = pos; itr != last; ++itr)
+ itr->~GenericValue();
+ std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
+ data_.a.size -= static_cast<SizeType>(last - first);
+ return pos;
+ }
+
+ Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
+ ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
+
+ //@}
+
+ //!@name Number
+ //@{
+
+ int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; }
+ unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; }
+ int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
+ uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
+
+ //! Get the value as double type.
+ /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
+ */
+ double GetDouble() const {
+ RAPIDJSON_ASSERT(IsNumber());
+ if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
+ if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double
+ if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
+ if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
+ RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
+ }
+
+ //! Get the value as float type.
+ /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless.
+ */
+ float GetFloat() const {
+ return static_cast<float>(GetDouble());
+ }
+
+ GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
+ GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
+ GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
+ GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
+ GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
+ GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
+
+ //@}
+
+ //!@name String
+ //@{
+
+ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
+
+ //! Get the length of string.
+ /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
+ */
+ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
+
+ //! Set this value as a string without copying source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string pointer.
+ \param length The length of source string, excluding the trailing null terminator.
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() == s && GetStringLength() == length
+ \see SetString(StringRefType)
+ */
+ GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
+
+ //! Set this value as a string without copying source string.
+ /*! \param s source string reference
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() == s && GetStringLength() == s.length
+ */
+ GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string.
+ \param length The length of source string, excluding the trailing null terminator.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
+#endif
+
+ //@}
+
+ //!@name Array
+ //@{
+
+ //! Templated version for checking whether this value is type T.
+ /*!
+ \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch>
+ */
+ template <typename T>
+ bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
+
+ template <typename T>
+ T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
+
+ template <typename T>
+ T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }
+
+ template<typename T>
+ ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }
+
+ template<typename T>
+ ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
+
+ //@}
+
+ //! Generate events of this value to a Handler.
+ /*! This function adopts the GoF visitor pattern.
+ Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
+ It can also be used to deep clone this value via GenericDocument, which is also a Handler.
+ \tparam Handler type of handler.
+ \param handler An object implementing concept Handler.
+ */
+ template <typename Handler>
+ bool Accept(Handler& handler) const {
+ switch(GetType()) {
+ case kNullType: return handler.Null();
+ case kFalseType: return handler.Bool(false);
+ case kTrueType: return handler.Bool(true);
+
+ case kObjectType:
+ if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
+ return false;
+ for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
+ RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
+ if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))
+ return false;
+ if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))
+ return false;
+ }
+ return handler.EndObject(data_.o.size);
+
+ case kArrayType:
+ if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
+ return false;
+ for (const GenericValue* v = Begin(); v != End(); ++v)
+ if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
+ return false;
+ return handler.EndArray(data_.a.size);
+
+ case kStringType:
+ return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
+
+ default:
+ RAPIDJSON_ASSERT(GetType() == kNumberType);
+ if (IsDouble()) return handler.Double(data_.n.d);
+ else if (IsInt()) return handler.Int(data_.n.i.i);
+ else if (IsUint()) return handler.Uint(data_.n.u.u);
+ else if (IsInt64()) return handler.Int64(data_.n.i64);
+ else return handler.Uint64(data_.n.u64);
+ }
+ }
+
+private:
+ template <typename, typename> friend class GenericValue;
+ template <typename, typename, typename> friend class GenericDocument;
+
+ enum {
+ kBoolFlag = 0x0008,
+ kNumberFlag = 0x0010,
+ kIntFlag = 0x0020,
+ kUintFlag = 0x0040,
+ kInt64Flag = 0x0080,
+ kUint64Flag = 0x0100,
+ kDoubleFlag = 0x0200,
+ kStringFlag = 0x0400,
+ kCopyFlag = 0x0800,
+ kInlineStrFlag = 0x1000,
+
+ // Initial flags of different types.
+ kNullFlag = kNullType,
+ kTrueFlag = kTrueType | kBoolFlag,
+ kFalseFlag = kFalseType | kBoolFlag,
+ kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
+ kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
+ kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
+ kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
+ kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
+ kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
+ kConstStringFlag = kStringType | kStringFlag,
+ kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
+ kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
+ kObjectFlag = kObjectType,
+ kArrayFlag = kArrayType,
+
+ kTypeMask = 0x07
+ };
+
+ static const SizeType kDefaultArrayCapacity = 16;
+ static const SizeType kDefaultObjectCapacity = 16;
+
+ struct Flag {
+#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
+ char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer
+#elif RAPIDJSON_64BIT
+ char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes
+#else
+ char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes
+#endif
+ uint16_t flags;
+ };
+
+ struct String {
+ SizeType length;
+ SizeType hashcode; //!< reserved
+ const Ch* str;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
+ // (excluding the terminating zero) and store a value to determine the length of the contained
+ // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
+ // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
+ // the string terminator as well. For getting the string length back from that value just use
+ // "MaxSize - str[LenPos]".
+ // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
+ // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).
+ struct ShortString {
+ enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
+ Ch str[MaxChars];
+
+ inline static bool Usable(SizeType len) { return (MaxSize >= len); }
+ inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); }
+ inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); }
+ }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // By using proper binary layout, retrieval of different integer types do not need conversions.
+ union Number {
+#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
+ struct I {
+ int i;
+ char padding[4];
+ }i;
+ struct U {
+ unsigned u;
+ char padding2[4];
+ }u;
+#else
+ struct I {
+ char padding[4];
+ int i;
+ }i;
+ struct U {
+ char padding2[4];
+ unsigned u;
+ }u;
+#endif
+ int64_t i64;
+ uint64_t u64;
+ double d;
+ }; // 8 bytes
+
+ struct ObjectData {
+ SizeType size;
+ SizeType capacity;
+ Member* members;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ struct ArrayData {
+ SizeType size;
+ SizeType capacity;
+ GenericValue* elements;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ union Data {
+ String s;
+ ShortString ss;
+ Number n;
+ ObjectData o;
+ ArrayData a;
+ Flag f;
+ }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+ RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
+ RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
+ RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
+ RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
+ RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
+ RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
+
+ // Initialize this value as array with initial data, without calling destructor.
+ void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
+ data_.f.flags = kArrayFlag;
+ if (count) {
+ GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
+ SetElementsPointer(e);
+ std::memcpy(e, values, count * sizeof(GenericValue));
+ }
+ else
+ SetElementsPointer(0);
+ data_.a.size = data_.a.capacity = count;
+ }
+
+ //! Initialize this value as object with initial data, without calling destructor.
+ void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
+ data_.f.flags = kObjectFlag;
+ if (count) {
+ Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
+ SetMembersPointer(m);
+ std::memcpy(m, members, count * sizeof(Member));
+ }
+ else
+ SetMembersPointer(0);
+ data_.o.size = data_.o.capacity = count;
+ }
+
+ //! Initialize this value as constant string, without calling destructor.
+ void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
+ data_.f.flags = kConstStringFlag;
+ SetStringPointer(s);
+ data_.s.length = s.length;
+ }
+
+ //! Initialize this value as copy string with initial data, without calling destructor.
+ void SetStringRaw(StringRefType s, Allocator& allocator) {
+ Ch* str = 0;
+ if (ShortString::Usable(s.length)) {
+ data_.f.flags = kShortStringFlag;
+ data_.ss.SetLength(s.length);
+ str = data_.ss.str;
+ } else {
+ data_.f.flags = kCopyStringFlag;
+ data_.s.length = s.length;
+ str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
+ SetStringPointer(str);
+ }
+ std::memcpy(str, s, s.length * sizeof(Ch));
+ str[s.length] = '\0';
+ }
+
+ //! Assignment without calling destructor
+ void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+ data_ = rhs.data_;
+ // data_.f.flags = rhs.data_.f.flags;
+ rhs.data_.f.flags = kNullFlag;
+ }
+
+ template <typename SourceAllocator>
+ bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+ RAPIDJSON_ASSERT(IsString());
+ RAPIDJSON_ASSERT(rhs.IsString());
+
+ const SizeType len1 = GetStringLength();
+ const SizeType len2 = rhs.GetStringLength();
+ if(len1 != len2) { return false; }
+
+ const Ch* const str1 = GetString();
+ const Ch* const str2 = rhs.GetString();
+ if(str1 == str2) { return true; } // fast path for constant string
+
+ return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
+ }
+
+ Data data_;
+};
+
+//! GenericValue with UTF8 encoding
+typedef GenericValue<UTF8<> > Value;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericDocument
+
+//! A document for parsing JSON text as DOM.
+/*!
+ \note implements Handler concept
+ \tparam Encoding Encoding for both parsing and string storage.
+ \tparam Allocator Allocator for allocating memory for the DOM
+ \tparam StackAllocator Allocator for allocating memory for stack during parsing.
+ \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
+class GenericDocument : public GenericValue<Encoding, Allocator> {
+public:
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+
+ //! Constructor
+ /*! Creates an empty document of specified type.
+ \param type Mandatory type of object to create.
+ \param allocator Optional allocator for allocating memory.
+ \param stackCapacity Optional initial capacity of stack in bytes.
+ \param stackAllocator Optional allocator for allocating memory for stack.
+ */
+ explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
+ GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ }
+
+ //! Constructor
+ /*! Creates an empty document which type is Null.
+ \param allocator Optional allocator for allocating memory.
+ \param stackCapacity Optional initial capacity of stack in bytes.
+ \param stackAllocator Optional allocator for allocating memory for stack.
+ */
+ GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
+ allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+ : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
+ allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ stack_(std::move(rhs.stack_)),
+ parseResult_(rhs.parseResult_)
+ {
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.parseResult_ = ParseResult();
+ }
+#endif
+
+ ~GenericDocument() {
+ Destroy();
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+ {
+ // The cast to ValueType is necessary here, because otherwise it would
+ // attempt to call GenericValue's templated assignment operator.
+ ValueType::operator=(std::forward<ValueType>(rhs));
+
+ // Calling the destructor here would prematurely call stack_'s destructor
+ Destroy();
+
+ allocator_ = rhs.allocator_;
+ ownAllocator_ = rhs.ownAllocator_;
+ stack_ = std::move(rhs.stack_);
+ parseResult_ = rhs.parseResult_;
+
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.parseResult_ = ParseResult();
+
+ return *this;
+ }
+#endif
+
+ //! Exchange the contents of this document with those of another.
+ /*!
+ \param rhs Another document.
+ \note Constant complexity.
+ \see GenericValue::Swap
+ */
+ GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
+ ValueType::Swap(rhs);
+ stack_.Swap(rhs.stack_);
+ internal::Swap(allocator_, rhs.allocator_);
+ internal::Swap(ownAllocator_, rhs.ownAllocator_);
+ internal::Swap(parseResult_, rhs.parseResult_);
+ return *this;
+ }
+
+ //! free-standing swap function helper
+ /*!
+ Helper function to enable support for common swap implementation pattern based on \c std::swap:
+ \code
+ void swap(MyClass& a, MyClass& b) {
+ using std::swap;
+ swap(a.doc, b.doc);
+ // ...
+ }
+ \endcode
+ \see Swap()
+ */
+ friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
+
+ //! Populate this document by a generator which produces SAX events.
+ /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
+ \param g Generator functor which sends SAX events to the parameter.
+ \return The document itself for fluent API.
+ */
+ template <typename Generator>
+ GenericDocument& Populate(Generator& g) {
+ ClearStackOnExit scope(*this);
+ if (g(*this)) {
+ RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+ ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
+ }
+ return *this;
+ }
+
+ //!@name Parse from stream
+ //!@{
+
+ //! Parse JSON text from an input stream (with Encoding conversion)
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam SourceEncoding Encoding of input stream
+ \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
+ stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
+ ClearStackOnExit scope(*this);
+ parseResult_ = reader.template Parse<parseFlags>(is, *this);
+ if (parseResult_) {
+ RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+ ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
+ }
+ return *this;
+ }
+
+ //! Parse JSON text from an input stream
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ return ParseStream<parseFlags, Encoding, InputStream>(is);
+ }
+
+ //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
+ /*! \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
+ }
+ //!@}
+
+ //!@name Parse in-place from mutable string
+ //!@{
+
+ //! Parse JSON text from a mutable string
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& ParseInsitu(Ch* str) {
+ GenericInsituStringStream<Encoding> s(str);
+ return ParseStream<parseFlags | kParseInsituFlag>(s);
+ }
+
+ //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
+ /*! \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ GenericDocument& ParseInsitu(Ch* str) {
+ return ParseInsitu<kParseDefaultFlags>(str);
+ }
+ //!@}
+
+ //!@name Parse from read-only string
+ //!@{
+
+ //! Parse JSON text from a read-only string (with Encoding conversion)
+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+ \tparam SourceEncoding Transcoding from input Encoding
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+ GenericStringStream<SourceEncoding> s(str);
+ return ParseStream<parseFlags, SourceEncoding>(s);
+ }
+
+ //! Parse JSON text from a read-only string
+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const Ch* str) {
+ return Parse<parseFlags, Encoding>(str);
+ }
+
+ //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
+ /*! \param str Read-only zero-terminated string to be parsed.
+ */
+ GenericDocument& Parse(const Ch* str) {
+ return Parse<kParseDefaultFlags>(str);
+ }
+
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+ MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
+ EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
+ ParseStream<parseFlags, SourceEncoding>(is);
+ return *this;
+ }
+
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const Ch* str, size_t length) {
+ return Parse<parseFlags, Encoding>(str, length);
+ }
+
+ GenericDocument& Parse(const Ch* str, size_t length) {
+ return Parse<kParseDefaultFlags>(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) {
+ // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t)
+ return Parse<parseFlags, SourceEncoding>(str.c_str());
+ }
+
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const std::basic_string<Ch>& str) {
+ return Parse<parseFlags, Encoding>(str.c_str());
+ }
+
+ GenericDocument& Parse(const std::basic_string<Ch>& str) {
+ return Parse<kParseDefaultFlags>(str);
+ }
+#endif // RAPIDJSON_HAS_STDSTRING
+
+ //!@}
+
+ //!@name Handling parse errors
+ //!@{
+
+ //! Whether a parse error has occured in the last parsing.
+ bool HasParseError() const { return parseResult_.IsError(); }
+
+ //! Get the \ref ParseErrorCode of last parsing.
+ ParseErrorCode GetParseError() const { return parseResult_.Code(); }
+
+ //! Get the position of last parsing error in input, 0 otherwise.
+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+ //! Implicit conversion to get the last parse result
+#ifndef __clang // -Wdocumentation
+ /*! \return \ref ParseResult of the last parse operation
+
+ \code
+ Document doc;
+ ParseResult ok = doc.Parse(json);
+ if (!ok)
+ printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset());
+ \endcode
+ */
+#endif
+ operator ParseResult() const { return parseResult_; }
+ //!@}
+
+ //! Get the allocator of this document.
+ Allocator& GetAllocator() {
+ RAPIDJSON_ASSERT(allocator_);
+ return *allocator_;
+ }
+
+ //! Get the capacity of stack in bytes.
+ size_t GetStackCapacity() const { return stack_.GetCapacity(); }
+
+private:
+ // clear stack on any exit from ParseStream, e.g. due to exception
+ struct ClearStackOnExit {
+ explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
+ ~ClearStackOnExit() { d_.ClearStack(); }
+ private:
+ ClearStackOnExit(const ClearStackOnExit&);
+ ClearStackOnExit& operator=(const ClearStackOnExit&);
+ GenericDocument& d_;
+ };
+
+ // callers of the following private Handler functions
+ // template <typename,typename,typename> friend class GenericReader; // for parsing
+ template <typename, typename> friend class GenericValue; // for deep copying
+
+public:
+ // Implementation of Handler
+ bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
+ bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
+ bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
+
+ bool RawNumber(const Ch* str, SizeType length, bool copy) {
+ if (copy)
+ new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+ else
+ new (stack_.template Push<ValueType>()) ValueType(str, length);
+ return true;
+ }
+
+ bool String(const Ch* str, SizeType length, bool copy) {
+ if (copy)
+ new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+ else
+ new (stack_.template Push<ValueType>()) ValueType(str, length);
+ return true;
+ }
+
+ bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
+
+ bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount) {
+ typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
+ stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
+ return true;
+ }
+
+ bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
+
+ bool EndArray(SizeType elementCount) {
+ ValueType* elements = stack_.template Pop<ValueType>(elementCount);
+ stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
+ return true;
+ }
+
+private:
+ //! Prohibit copying
+ GenericDocument(const GenericDocument&);
+ //! Prohibit assignment
+ GenericDocument& operator=(const GenericDocument&);
+
+ void ClearStack() {
+ if (Allocator::kNeedFree)
+ while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
+ (stack_.template Pop<ValueType>(1))->~ValueType();
+ else
+ stack_.Clear();
+ stack_.ShrinkToFit();
+ }
+
+ void Destroy() {
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ static const size_t kDefaultStackCapacity = 1024;
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ internal::Stack<StackAllocator> stack_;
+ ParseResult parseResult_;
+};
+
+//! GenericDocument with UTF8 encoding
+typedef GenericDocument<UTF8<> > Document;
+
+// defined here due to the dependency on GenericDocument
+template <typename Encoding, typename Allocator>
+template <typename SourceAllocator>
+inline
+GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
+{
+ switch (rhs.GetType()) {
+ case kObjectType:
+ case kArrayType: { // perform deep copy via SAX Handler
+ GenericDocument<Encoding,Allocator> d(&allocator);
+ rhs.Accept(d);
+ RawAssign(*d.stack_.template Pop<GenericValue>(1));
+ }
+ break;
+ case kStringType:
+ if (rhs.data_.f.flags == kConstStringFlag) {
+ data_.f.flags = rhs.data_.f.flags;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ } else {
+ SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
+ }
+ break;
+ default:
+ data_.f.flags = rhs.data_.f.flags;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ break;
+ }
+}
+
+//! Helper class for accessing Value of array type.
+/*!
+ Instance of this helper class is obtained by \c GenericValue::GetArray().
+ In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
+*/
+template <bool Const, typename ValueT>
+class GenericArray {
+public:
+ typedef GenericArray<true, ValueT> ConstArray;
+ typedef GenericArray<false, ValueT> Array;
+ typedef ValueT PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef ValueType* ValueIterator; // This may be const or non-const iterator
+ typedef const ValueT* ConstValueIterator;
+ typedef typename ValueType::AllocatorType AllocatorType;
+ typedef typename ValueType::StringRefType StringRefType;
+
+ template <typename, typename>
+ friend class GenericValue;
+
+ GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
+ GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
+ ~GenericArray() {}
+
+ SizeType Size() const { return value_.Size(); }
+ SizeType Capacity() const { return value_.Capacity(); }
+ bool Empty() const { return value_.Empty(); }
+ void Clear() const { value_.Clear(); }
+ ValueType& operator[](SizeType index) const { return value_[index]; }
+ ValueIterator Begin() const { return value_.Begin(); }
+ ValueIterator End() const { return value_.End(); }
+ GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }
+ GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+ GenericArray PopBack() const { value_.PopBack(); return *this; }
+ ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }
+ ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }
+
+#if RAPIDJSON_HAS_CXX11_RANGE_FOR
+ ValueIterator begin() const { return value_.Begin(); }
+ ValueIterator end() const { return value_.End(); }
+#endif
+
+private:
+ GenericArray();
+ GenericArray(ValueType& value) : value_(value) {}
+ ValueType& value_;
+};
+
+//! Helper class for accessing Value of object type.
+/*!
+ Instance of this helper class is obtained by \c GenericValue::GetObject().
+ In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
+*/
+template <bool Const, typename ValueT>
+class GenericObject {
+public:
+ typedef GenericObject<true, ValueT> ConstObject;
+ typedef GenericObject<false, ValueT> Object;
+ typedef ValueT PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator
+ typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator;
+ typedef typename ValueType::AllocatorType AllocatorType;
+ typedef typename ValueType::StringRefType StringRefType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename ValueType::Ch Ch;
+
+ template <typename, typename>
+ friend class GenericValue;
+
+ GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
+ GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
+ ~GenericObject() {}
+
+ SizeType MemberCount() const { return value_.MemberCount(); }
+ bool ObjectEmpty() const { return value_.ObjectEmpty(); }
+ template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
+ template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
+#if RAPIDJSON_HAS_STDSTRING
+ ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }
+#endif
+ MemberIterator MemberBegin() const { return value_.MemberBegin(); }
+ MemberIterator MemberEnd() const { return value_.MemberEnd(); }
+ bool HasMember(const Ch* name) const { return value_.HasMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
+#endif
+ template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
+ MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }
+ template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }
+#endif
+ GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#if RAPIDJSON_HAS_STDSTRING
+ GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#endif
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ void RemoveAllMembers() { return value_.RemoveAllMembers(); }
+ bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
+#endif
+ template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
+ MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }
+ MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }
+ MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }
+ bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }
+#endif
+ template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
+
+#if RAPIDJSON_HAS_CXX11_RANGE_FOR
+ MemberIterator begin() const { return value_.MemberBegin(); }
+ MemberIterator end() const { return value_.MemberEnd(); }
+#endif
+
+private:
+ GenericObject();
+ GenericObject(ValueType& value) : value_(value) {}
+ ValueType& value_;
+};
+
+RAPIDJSON_NAMESPACE_END
+RAPIDJSON_DIAG_POP
+
+#endif // RAPIDJSON_DOCUMENT_H_
diff --git a/include/rapidjson/encodedstream.h b/include/rapidjson/encodedstream.h
new file mode 100644
index 00000000..14506838
--- /dev/null
+++ b/include/rapidjson/encodedstream.h
@@ -0,0 +1,299 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ENCODEDSTREAM_H_
+#define RAPIDJSON_ENCODEDSTREAM_H_
+
+#include "stream.h"
+#include "memorystream.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Input byte stream wrapper with a statically bound encoding.
+/*!
+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+ \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
+*/
+template <typename Encoding, typename InputByteStream>
+class EncodedInputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+ typedef typename Encoding::Ch Ch;
+
+ EncodedInputStream(InputByteStream& is) : is_(is) {
+ current_ = Encoding::TakeBOM(is_);
+ }
+
+ Ch Peek() const { return current_; }
+ Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
+ size_t Tell() const { return is_.Tell(); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ EncodedInputStream(const EncodedInputStream&);
+ EncodedInputStream& operator=(const EncodedInputStream&);
+
+ InputByteStream& is_;
+ Ch current_;
+};
+
+//! Specialized for UTF8 MemoryStream.
+template <>
+class EncodedInputStream<UTF8<>, MemoryStream> {
+public:
+ typedef UTF8<>::Ch Ch;
+
+ EncodedInputStream(MemoryStream& is) : is_(is) {
+ if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
+ if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
+ if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
+ }
+ Ch Peek() const { return is_.Peek(); }
+ Ch Take() { return is_.Take(); }
+ size_t Tell() const { return is_.Tell(); }
+
+ // Not implemented
+ void Put(Ch) {}
+ void Flush() {}
+ Ch* PutBegin() { return 0; }
+ size_t PutEnd(Ch*) { return 0; }
+
+ MemoryStream& is_;
+
+private:
+ EncodedInputStream(const EncodedInputStream&);
+ EncodedInputStream& operator=(const EncodedInputStream&);
+};
+
+//! Output byte stream wrapper with statically bound encoding.
+/*!
+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+ \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
+*/
+template <typename Encoding, typename OutputByteStream>
+class EncodedOutputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+ typedef typename Encoding::Ch Ch;
+
+ EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
+ if (putBOM)
+ Encoding::PutBOM(os_);
+ }
+
+ void Put(Ch c) { Encoding::Put(os_, c); }
+ void Flush() { os_.Flush(); }
+
+ // Not implemented
+ Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
+ Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ EncodedOutputStream(const EncodedOutputStream&);
+ EncodedOutputStream& operator=(const EncodedOutputStream&);
+
+ OutputByteStream& os_;
+};
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+ \tparam CharType Type of character for reading.
+ \tparam InputByteStream type of input byte stream to be wrapped.
+*/
+template <typename CharType, typename InputByteStream>
+class AutoUTFInputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+ typedef CharType Ch;
+
+ //! Constructor.
+ /*!
+ \param is input stream to be wrapped.
+ \param type UTF encoding type if it is not detected from the stream.
+ */
+ AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
+ RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
+ DetectType();
+ static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
+ takeFunc_ = f[type_];
+ current_ = takeFunc_(*is_);
+ }
+
+ UTFType GetType() const { return type_; }
+ bool HasBOM() const { return hasBOM_; }
+
+ Ch Peek() const { return current_; }
+ Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
+ size_t Tell() const { return is_->Tell(); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ AutoUTFInputStream(const AutoUTFInputStream&);
+ AutoUTFInputStream& operator=(const AutoUTFInputStream&);
+
+ // Detect encoding type with BOM or RFC 4627
+ void DetectType() {
+ // BOM (Byte Order Mark):
+ // 00 00 FE FF UTF-32BE
+ // FF FE 00 00 UTF-32LE
+ // FE FF UTF-16BE
+ // FF FE UTF-16LE
+ // EF BB BF UTF-8
+
+ const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
+ if (!c)
+ return;
+
+ unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
+ hasBOM_ = false;
+ if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+ else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
+
+ // RFC 4627: Section 3
+ // "Since the first two characters of a JSON text will always be ASCII
+ // characters [RFC0020], it is possible to determine whether an octet
+ // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
+ // at the pattern of nulls in the first four octets."
+ // 00 00 00 xx UTF-32BE
+ // 00 xx 00 xx UTF-16BE
+ // xx 00 00 00 UTF-32LE
+ // xx 00 xx 00 UTF-16LE
+ // xx xx xx xx UTF-8
+
+ if (!hasBOM_) {
+ unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
+ switch (pattern) {
+ case 0x08: type_ = kUTF32BE; break;
+ case 0x0A: type_ = kUTF16BE; break;
+ case 0x01: type_ = kUTF32LE; break;
+ case 0x05: type_ = kUTF16LE; break;
+ case 0x0F: type_ = kUTF8; break;
+ default: break; // Use type defined by user.
+ }
+ }
+
+ // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+ if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+ if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+ }
+
+ typedef Ch (*TakeFunc)(InputByteStream& is);
+ InputByteStream* is_;
+ UTFType type_;
+ Ch current_;
+ TakeFunc takeFunc_;
+ bool hasBOM_;
+};
+
+//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+ \tparam CharType Type of character for writing.
+ \tparam OutputByteStream type of output byte stream to be wrapped.
+*/
+template <typename CharType, typename OutputByteStream>
+class AutoUTFOutputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+ typedef CharType Ch;
+
+ //! Constructor.
+ /*!
+ \param os output stream to be wrapped.
+ \param type UTF encoding type.
+ \param putBOM Whether to write BOM at the beginning of the stream.
+ */
+ AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
+ RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
+
+ // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+ if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+ if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+
+ static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
+ putFunc_ = f[type_];
+
+ if (putBOM)
+ PutBOM();
+ }
+
+ UTFType GetType() const { return type_; }
+
+ void Put(Ch c) { putFunc_(*os_, c); }
+ void Flush() { os_->Flush(); }
+
+ // Not implemented
+ Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
+ Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ AutoUTFOutputStream(const AutoUTFOutputStream&);
+ AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
+
+ void PutBOM() {
+ typedef void (*PutBOMFunc)(OutputByteStream&);
+ static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
+ f[type_](*os_);
+ }
+
+ typedef void (*PutFunc)(OutputByteStream&, Ch);
+
+ OutputByteStream* os_;
+ UTFType type_;
+ PutFunc putFunc_;
+};
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/include/rapidjson/encodings.h b/include/rapidjson/encodings.h
new file mode 100644
index 00000000..baa7c2b1
--- /dev/null
+++ b/include/rapidjson/encodings.h
@@ -0,0 +1,716 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ENCODINGS_H_
+#define RAPIDJSON_ENCODINGS_H_
+
+#include "rapidjson.h"
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
+RAPIDJSON_DIAG_OFF(4702) // unreachable code
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+RAPIDJSON_DIAG_OFF(overflow)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Encoding
+
+/*! \class rapidjson::Encoding
+ \brief Concept for encoding of Unicode characters.
+
+\code
+concept Encoding {
+ typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
+
+ enum { supportUnicode = 1 }; // or 0 if not supporting unicode
+
+ //! \brief Encode a Unicode codepoint to an output stream.
+ //! \param os Output stream.
+ //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint);
+
+ //! \brief Decode a Unicode codepoint from an input stream.
+ //! \param is Input stream.
+ //! \param codepoint Output of the unicode codepoint.
+ //! \return true if a valid codepoint can be decoded from the stream.
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint);
+
+ //! \brief Validate one Unicode codepoint from an encoded stream.
+ //! \param is Input stream to obtain codepoint.
+ //! \param os Output for copying one codepoint.
+ //! \return true if it is valid.
+ //! \note This function just validating and copying the codepoint without actually decode it.
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os);
+
+ // The following functions are deal with byte streams.
+
+ //! Take a character from input byte stream, skip BOM if exist.
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is);
+
+ //! Take a character from input byte stream.
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is);
+
+ //! Put BOM to output byte stream.
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os);
+
+ //! Put a character to output byte stream.
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF8
+
+//! UTF-8 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-8
+ http://tools.ietf.org/html/rfc3629
+ \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
+ \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct UTF8 {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ if (codepoint <= 0x7F)
+ os.Put(static_cast<Ch>(codepoint & 0xFF));
+ else if (codepoint <= 0x7FF) {
+ os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+ }
+ else if (codepoint <= 0xFFFF) {
+ os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ }
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ if (codepoint <= 0x7F)
+ PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
+ else if (codepoint <= 0x7FF) {
+ PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+ }
+ else if (codepoint <= 0xFFFF) {
+ PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
+#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+ typename InputStream::Ch c = is.Take();
+ if (!(c & 0x80)) {
+ *codepoint = static_cast<unsigned char>(c);
+ return true;
+ }
+
+ unsigned char type = GetRange(static_cast<unsigned char>(c));
+ if (type >= 32) {
+ *codepoint = 0;
+ } else {
+ *codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
+ }
+ bool result = true;
+ switch (type) {
+ case 2: TAIL(); return result;
+ case 3: TAIL(); TAIL(); return result;
+ case 4: COPY(); TRANS(0x50); TAIL(); return result;
+ case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+ case 6: TAIL(); TAIL(); TAIL(); return result;
+ case 10: COPY(); TRANS(0x20); TAIL(); return result;
+ case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+ default: return false;
+ }
+#undef COPY
+#undef TRANS
+#undef TAIL
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+#define COPY() os.Put(c = is.Take())
+#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+ Ch c;
+ COPY();
+ if (!(c & 0x80))
+ return true;
+
+ bool result = true;
+ switch (GetRange(static_cast<unsigned char>(c))) {
+ case 2: TAIL(); return result;
+ case 3: TAIL(); TAIL(); return result;
+ case 4: COPY(); TRANS(0x50); TAIL(); return result;
+ case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+ case 6: TAIL(); TAIL(); TAIL(); return result;
+ case 10: COPY(); TRANS(0x20); TAIL(); return result;
+ case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+ default: return false;
+ }
+#undef COPY
+#undef TRANS
+#undef TAIL
+ }
+
+ static unsigned char GetRange(unsigned char c) {
+ // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+ // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
+ static const unsigned char type[] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
+ };
+ return type[c];
+ }
+
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ typename InputByteStream::Ch c = Take(is);
+ if (static_cast<unsigned char>(c) != 0xEFu) return c;
+ c = is.Take();
+ if (static_cast<unsigned char>(c) != 0xBBu) return c;
+ c = is.Take();
+ if (static_cast<unsigned char>(c) != 0xBFu) return c;
+ c = is.Take();
+ return c;
+ }
+
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ return static_cast<Ch>(is.Take());
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF16
+
+//! UTF-16 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-16
+ http://tools.ietf.org/html/rfc2781
+ \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
+ \note implements Encoding concept
+
+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+ For streaming, use UTF16LE and UTF16BE, which handle endianness.
+*/
+template<typename CharType = wchar_t>
+struct UTF16 {
+ typedef CharType Ch;
+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ if (codepoint <= 0xFFFF) {
+ RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
+ os.Put(static_cast<typename OutputStream::Ch>(codepoint));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ unsigned v = codepoint - 0x10000;
+ os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+ os.Put((v & 0x3FF) | 0xDC00);
+ }
+ }
+
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ if (codepoint <= 0xFFFF) {
+ RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
+ PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ unsigned v = codepoint - 0x10000;
+ PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+ PutUnsafe(os, (v & 0x3FF) | 0xDC00);
+ }
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+ typename InputStream::Ch c = is.Take();
+ if (c < 0xD800 || c > 0xDFFF) {
+ *codepoint = static_cast<unsigned>(c);
+ return true;
+ }
+ else if (c <= 0xDBFF) {
+ *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
+ c = is.Take();
+ *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
+ *codepoint += 0x10000;
+ return c >= 0xDC00 && c <= 0xDFFF;
+ }
+ return false;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ typename InputStream::Ch c;
+ os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
+ if (c < 0xD800 || c > 0xDFFF)
+ return true;
+ else if (c <= 0xDBFF) {
+ os.Put(c = is.Take());
+ return c >= 0xDC00 && c <= 0xDFFF;
+ }
+ return false;
+ }
+};
+
+//! UTF-16 little endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16LE : UTF16<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ unsigned c = static_cast<uint8_t>(is.Take());
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ return static_cast<CharType>(c);
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
+ }
+};
+
+//! UTF-16 big endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16BE : UTF16<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<uint8_t>(is.Take());
+ return static_cast<CharType>(c);
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF32
+
+//! UTF-32 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-32
+ \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
+ \note implements Encoding concept
+
+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+ For streaming, use UTF32LE and UTF32BE, which handle endianness.
+*/
+template<typename CharType = unsigned>
+struct UTF32 {
+ typedef CharType Ch;
+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ os.Put(codepoint);
+ }
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ PutUnsafe(os, codepoint);
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+ Ch c = is.Take();
+ *codepoint = c;
+ return c <= 0x10FFFF;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+ Ch c;
+ os.Put(c = is.Take());
+ return c <= 0x10FFFF;
+ }
+};
+
+//! UTF-32 little endian enocoding.
+template<typename CharType = unsigned>
+struct UTF32LE : UTF32<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ unsigned c = static_cast<uint8_t>(is.Take());
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
+ return static_cast<CharType>(c);
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
+ }
+};
+
+//! UTF-32 big endian encoding.
+template<typename CharType = unsigned>
+struct UTF32BE : UTF32<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
+ return static_cast<CharType>(c);
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ASCII
+
+//! ASCII encoding.
+/*! http://en.wikipedia.org/wiki/ASCII
+ \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
+ \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct ASCII {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 0 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_ASSERT(codepoint <= 0x7F);
+ os.Put(static_cast<Ch>(codepoint & 0xFF));
+ }
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_ASSERT(codepoint <= 0x7F);
+ PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ uint8_t c = static_cast<uint8_t>(is.Take());
+ *codepoint = c;
+ return c <= 0X7F;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ uint8_t c = static_cast<uint8_t>(is.Take());
+ os.Put(static_cast<typename OutputStream::Ch>(c));
+ return c <= 0x7F;
+ }
+
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ uint8_t c = static_cast<uint8_t>(Take(is));
+ return static_cast<Ch>(c);
+ }
+
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ return static_cast<Ch>(is.Take());
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ (void)os;
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// AutoUTF
+
+//! Runtime-specified UTF encoding type of a stream.
+enum UTFType {
+ kUTF8 = 0, //!< UTF-8.
+ kUTF16LE = 1, //!< UTF-16 little endian.
+ kUTF16BE = 2, //!< UTF-16 big endian.
+ kUTF32LE = 3, //!< UTF-32 little endian.
+ kUTF32BE = 4 //!< UTF-32 big endian.
+};
+
+//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
+/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
+*/
+template<typename CharType>
+struct AutoUTF {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 1 };
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+ template<typename OutputStream>
+ RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
+ typedef void (*EncodeFunc)(OutputStream&, unsigned);
+ static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
+ (*f[os.GetType()])(os, codepoint);
+ }
+
+ template<typename OutputStream>
+ RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ typedef void (*EncodeFunc)(OutputStream&, unsigned);
+ static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
+ (*f[os.GetType()])(os, codepoint);
+ }
+
+ template <typename InputStream>
+ RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
+ typedef bool (*DecodeFunc)(InputStream&, unsigned*);
+ static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
+ return (*f[is.GetType()])(is, codepoint);
+ }
+
+ template <typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
+ static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
+ return (*f[is.GetType()])(is, os);
+ }
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Transcoder
+
+//! Encoding conversion.
+template<typename SourceEncoding, typename TargetEncoding>
+struct Transcoder {
+ //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ TargetEncoding::Encode(os, codepoint);
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ TargetEncoding::EncodeUnsafe(os, codepoint);
+ return true;
+ }
+
+ //! Validate one Unicode codepoint from an encoded stream.
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ return Transcode(is, os); // Since source/target encoding is different, must transcode.
+ }
+};
+
+// Forward declaration.
+template<typename Stream>
+inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
+
+//! Specialization of Transcoder with same source and target encoding.
+template<typename Encoding>
+struct Transcoder<Encoding, Encoding> {
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+ os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
+ PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ return Encoding::Validate(is, os); // source/target encoding are the same
+ }
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/include/rapidjson/error/en.h b/include/rapidjson/error/en.h
new file mode 100644
index 00000000..2db838bf
--- /dev/null
+++ b/include/rapidjson/error/en.h
@@ -0,0 +1,74 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ERROR_EN_H_
+#define RAPIDJSON_ERROR_EN_H_
+
+#include "error.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(covered-switch-default)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Maps error code of parsing into error message.
+/*!
+ \ingroup RAPIDJSON_ERRORS
+ \param parseErrorCode Error code obtained in parsing.
+ \return the error message.
+ \note User can make a copy of this function for localization.
+ Using switch-case is safer for future modification of error codes.
+*/
+inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
+ switch (parseErrorCode) {
+ case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
+
+ case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
+ case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
+
+ case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
+
+ case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
+ case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
+ case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
+
+ case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
+
+ case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
+ case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
+ case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
+ case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
+ case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
+
+ case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
+ case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
+ case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
+
+ case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
+ case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
+
+ default: return RAPIDJSON_ERROR_STRING("Unknown error.");
+ }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ERROR_EN_H_
diff --git a/include/rapidjson/error/error.h b/include/rapidjson/error/error.h
new file mode 100644
index 00000000..95cb31a7
--- /dev/null
+++ b/include/rapidjson/error/error.h
@@ -0,0 +1,155 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ERROR_ERROR_H_
+#define RAPIDJSON_ERROR_ERROR_H_
+
+#include "../rapidjson.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+/*! \file error.h */
+
+/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_CHARTYPE
+
+//! Character type of error messages.
+/*! \ingroup RAPIDJSON_ERRORS
+ The default character type is \c char.
+ On Windows, user can define this macro as \c TCHAR for supporting both
+ unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_CHARTYPE
+#define RAPIDJSON_ERROR_CHARTYPE char
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_STRING
+
+//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
+/*! \ingroup RAPIDJSON_ERRORS
+ By default this conversion macro does nothing.
+ On Windows, user can define this macro as \c _T(x) for supporting both
+ unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_STRING
+#define RAPIDJSON_ERROR_STRING(x) x
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseErrorCode
+
+//! Error code of parsing.
+/*! \ingroup RAPIDJSON_ERRORS
+ \see GenericReader::Parse, GenericReader::GetParseErrorCode
+*/
+enum ParseErrorCode {
+ kParseErrorNone = 0, //!< No error.
+
+ kParseErrorDocumentEmpty, //!< The document is empty.
+ kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
+
+ kParseErrorValueInvalid, //!< Invalid value.
+
+ kParseErrorObjectMissName, //!< Missing a name for object member.
+ kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
+ kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
+
+ kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
+
+ kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
+ kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
+ kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
+ kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
+ kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
+
+ kParseErrorNumberTooBig, //!< Number too big to be stored in double.
+ kParseErrorNumberMissFraction, //!< Miss fraction part in number.
+ kParseErrorNumberMissExponent, //!< Miss exponent in number.
+
+ kParseErrorTermination, //!< Parsing was terminated.
+ kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
+};
+
+//! Result of parsing (wraps ParseErrorCode)
+/*!
+ \ingroup RAPIDJSON_ERRORS
+ \code
+ Document doc;
+ ParseResult ok = doc.Parse("[42]");
+ if (!ok) {
+ fprintf(stderr, "JSON parse error: %s (%u)",
+ GetParseError_En(ok.Code()), ok.Offset());
+ exit(EXIT_FAILURE);
+ }
+ \endcode
+ \see GenericReader::Parse, GenericDocument::Parse
+*/
+struct ParseResult {
+public:
+ //! Default constructor, no error.
+ ParseResult() : code_(kParseErrorNone), offset_(0) {}
+ //! Constructor to set an error.
+ ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
+
+ //! Get the error code.
+ ParseErrorCode Code() const { return code_; }
+ //! Get the error offset, if \ref IsError(), 0 otherwise.
+ size_t Offset() const { return offset_; }
+
+ //! Conversion to \c bool, returns \c true, iff !\ref IsError().
+ operator bool() const { return !IsError(); }
+ //! Whether the result is an error.
+ bool IsError() const { return code_ != kParseErrorNone; }
+
+ bool operator==(const ParseResult& that) const { return code_ == that.code_; }
+ bool operator==(ParseErrorCode code) const { return code_ == code; }
+ friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
+
+ //! Reset error code.
+ void Clear() { Set(kParseErrorNone); }
+ //! Update error code and offset.
+ void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
+
+private:
+ ParseErrorCode code_;
+ size_t offset_;
+};
+
+//! Function pointer type of GetParseError().
+/*! \ingroup RAPIDJSON_ERRORS
+
+ This is the prototype for \c GetParseError_X(), where \c X is a locale.
+ User can dynamically change locale in runtime, e.g.:
+\code
+ GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
+ const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
+\endcode
+*/
+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ERROR_ERROR_H_
diff --git a/include/rapidjson/filereadstream.h b/include/rapidjson/filereadstream.h
new file mode 100644
index 00000000..b56ea13b
--- /dev/null
+++ b/include/rapidjson/filereadstream.h
@@ -0,0 +1,99 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FILEREADSTREAM_H_
+#define RAPIDJSON_FILEREADSTREAM_H_
+
+#include "stream.h"
+#include <cstdio>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(unreachable-code)
+RAPIDJSON_DIAG_OFF(missing-noreturn)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! File byte stream for input using fread().
+/*!
+ \note implements Stream concept
+*/
+class FileReadStream {
+public:
+ typedef char Ch; //!< Character type (byte).
+
+ //! Constructor.
+ /*!
+ \param fp File pointer opened for read.
+ \param buffer user-supplied buffer.
+ \param bufferSize size of buffer in bytes. Must >=4 bytes.
+ */
+ FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ RAPIDJSON_ASSERT(bufferSize >= 4);
+ Read();
+ }
+
+ Ch Peek() const { return *current_; }
+ Ch Take() { Ch c = *current_; Read(); return c; }
+ size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ // For encoding detection only.
+ const Ch* Peek4() const {
+ return (current_ + 4 <= bufferLast_) ? current_ : 0;
+ }
+
+private:
+ void Read() {
+ if (current_ < bufferLast_)
+ ++current_;
+ else if (!eof_) {
+ count_ += readCount_;
+ readCount_ = fread(buffer_, 1, bufferSize_, fp_);
+ bufferLast_ = buffer_ + readCount_ - 1;
+ current_ = buffer_;
+
+ if (readCount_ < bufferSize_) {
+ buffer_[readCount_] = '\0';
+ ++bufferLast_;
+ eof_ = true;
+ }
+ }
+ }
+
+ std::FILE* fp_;
+ Ch *buffer_;
+ size_t bufferSize_;
+ Ch *bufferLast_;
+ Ch *current_;
+ size_t readCount_;
+ size_t count_; //!< Number of characters read
+ bool eof_;
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/include/rapidjson/filewritestream.h b/include/rapidjson/filewritestream.h
new file mode 100644
index 00000000..6378dd60
--- /dev/null
+++ b/include/rapidjson/filewritestream.h
@@ -0,0 +1,104 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FILEWRITESTREAM_H_
+#define RAPIDJSON_FILEWRITESTREAM_H_
+
+#include "stream.h"
+#include <cstdio>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(unreachable-code)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of C file stream for input using fread().
+/*!
+ \note implements Stream concept
+*/
+class FileWriteStream {
+public:
+ typedef char Ch; //!< Character type. Only support char.
+
+ FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ }
+
+ void Put(char c) {
+ if (current_ >= bufferEnd_)
+ Flush();
+
+ *current_++ = c;
+ }
+
+ void PutN(char c, size_t n) {
+ size_t avail = static_cast<size_t>(bufferEnd_ - current_);
+ while (n > avail) {
+ std::memset(current_, c, avail);
+ current_ += avail;
+ Flush();
+ n -= avail;
+ avail = static_cast<size_t>(bufferEnd_ - current_);
+ }
+
+ if (n > 0) {
+ std::memset(current_, c, n);
+ current_ += n;
+ }
+ }
+
+ void Flush() {
+ if (current_ != buffer_) {
+ size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
+ if (result < static_cast<size_t>(current_ - buffer_)) {
+ // failure deliberately ignored at this time
+ // added to avoid warn_unused_result build errors
+ }
+ current_ = buffer_;
+ }
+ }
+
+ // Not implemented
+ char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
+ char Take() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ FileWriteStream(const FileWriteStream&);
+ FileWriteStream& operator=(const FileWriteStream&);
+
+ std::FILE* fp_;
+ char *buffer_;
+ char *bufferEnd_;
+ char *current_;
+};
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(FileWriteStream& stream, char c, size_t n) {
+ stream.PutN(c, n);
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/include/rapidjson/fwd.h b/include/rapidjson/fwd.h
new file mode 100644
index 00000000..e8104e84
--- /dev/null
+++ b/include/rapidjson/fwd.h
@@ -0,0 +1,151 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FWD_H_
+#define RAPIDJSON_FWD_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// encodings.h
+
+template<typename CharType> struct UTF8;
+template<typename CharType> struct UTF16;
+template<typename CharType> struct UTF16BE;
+template<typename CharType> struct UTF16LE;
+template<typename CharType> struct UTF32;
+template<typename CharType> struct UTF32BE;
+template<typename CharType> struct UTF32LE;
+template<typename CharType> struct ASCII;
+template<typename CharType> struct AutoUTF;
+
+template<typename SourceEncoding, typename TargetEncoding>
+struct Transcoder;
+
+// allocators.h
+
+class CrtAllocator;
+
+template <typename BaseAllocator>
+class MemoryPoolAllocator;
+
+// stream.h
+
+template <typename Encoding>
+struct GenericStringStream;
+
+typedef GenericStringStream<UTF8<char> > StringStream;
+
+template <typename Encoding>
+struct GenericInsituStringStream;
+
+typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
+
+// stringbuffer.h
+
+template <typename Encoding, typename Allocator>
+class GenericStringBuffer;
+
+typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
+
+// filereadstream.h
+
+class FileReadStream;
+
+// filewritestream.h
+
+class FileWriteStream;
+
+// memorybuffer.h
+
+template <typename Allocator>
+struct GenericMemoryBuffer;
+
+typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
+
+// memorystream.h
+
+struct MemoryStream;
+
+// reader.h
+
+template<typename Encoding, typename Derived>
+struct BaseReaderHandler;
+
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
+class GenericReader;
+
+typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
+
+// writer.h
+
+template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
+class Writer;
+
+// prettywriter.h
+
+template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
+class PrettyWriter;
+
+// document.h
+
+template <typename Encoding, typename Allocator>
+struct GenericMember;
+
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator;
+
+template<typename CharType>
+struct GenericStringRef;
+
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
+
+template <typename Encoding, typename Allocator, typename StackAllocator>
+class GenericDocument;
+
+typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;
+
+// pointer.h
+
+template <typename ValueType, typename Allocator>
+class GenericPointer;
+
+typedef GenericPointer<Value, CrtAllocator> Pointer;
+
+// schema.h
+
+template <typename SchemaDocumentType>
+class IGenericRemoteSchemaDocumentProvider;
+
+template <typename ValueT, typename Allocator>
+class GenericSchemaDocument;
+
+typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
+typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
+
+template <
+ typename SchemaDocumentType,
+ typename OutputHandler,
+ typename StateAllocator>
+class GenericSchemaValidator;
+
+typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSONFWD_H_
diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h
new file mode 100644
index 00000000..9d3e88c9
--- /dev/null
+++ b/include/rapidjson/internal/biginteger.h
@@ -0,0 +1,290 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_BIGINTEGER_H_
+#define RAPIDJSON_BIGINTEGER_H_
+
+#include "../rapidjson.h"
+
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#include <intrin.h> // for _umul128
+#pragma intrinsic(_umul128)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class BigInteger {
+public:
+ typedef uint64_t Type;
+
+ BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
+ std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
+ }
+
+ explicit BigInteger(uint64_t u) : count_(1) {
+ digits_[0] = u;
+ }
+
+ BigInteger(const char* decimals, size_t length) : count_(1) {
+ RAPIDJSON_ASSERT(length > 0);
+ digits_[0] = 0;
+ size_t i = 0;
+ const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
+ while (length >= kMaxDigitPerIteration) {
+ AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
+ length -= kMaxDigitPerIteration;
+ i += kMaxDigitPerIteration;
+ }
+
+ if (length > 0)
+ AppendDecimal64(decimals + i, decimals + i + length);
+ }
+
+ BigInteger& operator=(const BigInteger &rhs)
+ {
+ if (this != &rhs) {
+ count_ = rhs.count_;
+ std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
+ }
+ return *this;
+ }
+
+ BigInteger& operator=(uint64_t u) {
+ digits_[0] = u;
+ count_ = 1;
+ return *this;
+ }
+
+ BigInteger& operator+=(uint64_t u) {
+ Type backup = digits_[0];
+ digits_[0] += u;
+ for (size_t i = 0; i < count_ - 1; i++) {
+ if (digits_[i] >= backup)
+ return *this; // no carry
+ backup = digits_[i + 1];
+ digits_[i + 1] += 1;
+ }
+
+ // Last carry
+ if (digits_[count_ - 1] < backup)
+ PushBack(1);
+
+ return *this;
+ }
+
+ BigInteger& operator*=(uint64_t u) {
+ if (u == 0) return *this = 0;
+ if (u == 1) return *this;
+ if (*this == 1) return *this = u;
+
+ uint64_t k = 0;
+ for (size_t i = 0; i < count_; i++) {
+ uint64_t hi;
+ digits_[i] = MulAdd64(digits_[i], u, k, &hi);
+ k = hi;
+ }
+
+ if (k > 0)
+ PushBack(k);
+
+ return *this;
+ }
+
+ BigInteger& operator*=(uint32_t u) {
+ if (u == 0) return *this = 0;
+ if (u == 1) return *this;
+ if (*this == 1) return *this = u;
+
+ uint64_t k = 0;
+ for (size_t i = 0; i < count_; i++) {
+ const uint64_t c = digits_[i] >> 32;
+ const uint64_t d = digits_[i] & 0xFFFFFFFF;
+ const uint64_t uc = u * c;
+ const uint64_t ud = u * d;
+ const uint64_t p0 = ud + k;
+ const uint64_t p1 = uc + (p0 >> 32);
+ digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
+ k = p1 >> 32;
+ }
+
+ if (k > 0)
+ PushBack(k);
+
+ return *this;
+ }
+
+ BigInteger& operator<<=(size_t shift) {
+ if (IsZero() || shift == 0) return *this;
+
+ size_t offset = shift / kTypeBit;
+ size_t interShift = shift % kTypeBit;
+ RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
+
+ if (interShift == 0) {
+ std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
+ count_ += offset;
+ }
+ else {
+ digits_[count_] = 0;
+ for (size_t i = count_; i > 0; i--)
+ digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
+ digits_[offset] = digits_[0] << interShift;
+ count_ += offset;
+ if (digits_[count_])
+ count_++;
+ }
+
+ std::memset(digits_, 0, offset * sizeof(Type));
+
+ return *this;
+ }
+
+ bool operator==(const BigInteger& rhs) const {
+ return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
+ }
+
+ bool operator==(const Type rhs) const {
+ return count_ == 1 && digits_[0] == rhs;
+ }
+
+ BigInteger& MultiplyPow5(unsigned exp) {
+ static const uint32_t kPow5[12] = {
+ 5,
+ 5 * 5,
+ 5 * 5 * 5,
+ 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+ };
+ if (exp == 0) return *this;
+ for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
+ for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
+ if (exp > 0) *this *= kPow5[exp - 1];
+ return *this;
+ }
+
+ // Compute absolute difference of this and rhs.
+ // Assume this != rhs
+ bool Difference(const BigInteger& rhs, BigInteger* out) const {
+ int cmp = Compare(rhs);
+ RAPIDJSON_ASSERT(cmp != 0);
+ const BigInteger *a, *b; // Makes a > b
+ bool ret;
+ if (cmp < 0) { a = &rhs; b = this; ret = true; }
+ else { a = this; b = &rhs; ret = false; }
+
+ Type borrow = 0;
+ for (size_t i = 0; i < a->count_; i++) {
+ Type d = a->digits_[i] - borrow;
+ if (i < b->count_)
+ d -= b->digits_[i];
+ borrow = (d > a->digits_[i]) ? 1 : 0;
+ out->digits_[i] = d;
+ if (d != 0)
+ out->count_ = i + 1;
+ }
+
+ return ret;
+ }
+
+ int Compare(const BigInteger& rhs) const {
+ if (count_ != rhs.count_)
+ return count_ < rhs.count_ ? -1 : 1;
+
+ for (size_t i = count_; i-- > 0;)
+ if (digits_[i] != rhs.digits_[i])
+ return digits_[i] < rhs.digits_[i] ? -1 : 1;
+
+ return 0;
+ }
+
+ size_t GetCount() const { return count_; }
+ Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
+ bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
+
+private:
+ void AppendDecimal64(const char* begin, const char* end) {
+ uint64_t u = ParseUint64(begin, end);
+ if (IsZero())
+ *this = u;
+ else {
+ unsigned exp = static_cast<unsigned>(end - begin);
+ (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
+ }
+ }
+
+ void PushBack(Type digit) {
+ RAPIDJSON_ASSERT(count_ < kCapacity);
+ digits_[count_++] = digit;
+ }
+
+ static uint64_t ParseUint64(const char* begin, const char* end) {
+ uint64_t r = 0;
+ for (const char* p = begin; p != end; ++p) {
+ RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
+ r = r * 10u + static_cast<unsigned>(*p - '0');
+ }
+ return r;
+ }
+
+ // Assume a * b + k < 2^128
+ static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ uint64_t low = _umul128(a, b, outHigh) + k;
+ if (low < k)
+ (*outHigh)++;
+ return low;
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+ __extension__ typedef unsigned __int128 uint128;
+ uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
+ p += k;
+ *outHigh = static_cast<uint64_t>(p >> 64);
+ return static_cast<uint64_t>(p);
+#else
+ const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
+ uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
+ x1 += (x0 >> 32); // can't give carry
+ x1 += x2;
+ if (x1 < x2)
+ x3 += (static_cast<uint64_t>(1) << 32);
+ uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
+ uint64_t hi = x3 + (x1 >> 32);
+
+ lo += k;
+ if (lo < k)
+ hi++;
+ *outHigh = hi;
+ return lo;
+#endif
+ }
+
+ static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
+ static const size_t kCapacity = kBitCount / sizeof(Type);
+ static const size_t kTypeBit = sizeof(Type) * 8;
+
+ Type digits_[kCapacity];
+ size_t count_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_BIGINTEGER_H_
diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h
new file mode 100644
index 00000000..c9fefdc6
--- /dev/null
+++ b/include/rapidjson/internal/diyfp.h
@@ -0,0 +1,258 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DIYFP_H_
+#define RAPIDJSON_DIYFP_H_
+
+#include "../rapidjson.h"
+
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#include <intrin.h>
+#pragma intrinsic(_BitScanReverse64)
+#pragma intrinsic(_umul128)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+struct DiyFp {
+ DiyFp() : f(), e() {}
+
+ DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
+
+ explicit DiyFp(double d) {
+ union {
+ double d;
+ uint64_t u64;
+ } u = { d };
+
+ int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
+ uint64_t significand = (u.u64 & kDpSignificandMask);
+ if (biased_e != 0) {
+ f = significand + kDpHiddenBit;
+ e = biased_e - kDpExponentBias;
+ }
+ else {
+ f = significand;
+ e = kDpMinExponent + 1;
+ }
+ }
+
+ DiyFp operator-(const DiyFp& rhs) const {
+ return DiyFp(f - rhs.f, e);
+ }
+
+ DiyFp operator*(const DiyFp& rhs) const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ uint64_t h;
+ uint64_t l = _umul128(f, rhs.f, &h);
+ if (l & (uint64_t(1) << 63)) // rounding
+ h++;
+ return DiyFp(h, e + rhs.e + 64);
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+ __extension__ typedef unsigned __int128 uint128;
+ uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
+ uint64_t h = static_cast<uint64_t>(p >> 64);
+ uint64_t l = static_cast<uint64_t>(p);
+ if (l & (uint64_t(1) << 63)) // rounding
+ h++;
+ return DiyFp(h, e + rhs.e + 64);
+#else
+ const uint64_t M32 = 0xFFFFFFFF;
+ const uint64_t a = f >> 32;
+ const uint64_t b = f & M32;
+ const uint64_t c = rhs.f >> 32;
+ const uint64_t d = rhs.f & M32;
+ const uint64_t ac = a * c;
+ const uint64_t bc = b * c;
+ const uint64_t ad = a * d;
+ const uint64_t bd = b * d;
+ uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
+ tmp += 1U << 31; /// mult_round
+ return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
+#endif
+ }
+
+ DiyFp Normalize() const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ unsigned long index;
+ _BitScanReverse64(&index, f);
+ return DiyFp(f << (63 - index), e - (63 - index));
+#elif defined(__GNUC__) && __GNUC__ >= 4
+ int s = __builtin_clzll(f);
+ return DiyFp(f << s, e - s);
+#else
+ DiyFp res = *this;
+ while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
+ res.f <<= 1;
+ res.e--;
+ }
+ return res;
+#endif
+ }
+
+ DiyFp NormalizeBoundary() const {
+ DiyFp res = *this;
+ while (!(res.f & (kDpHiddenBit << 1))) {
+ res.f <<= 1;
+ res.e--;
+ }
+ res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
+ res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
+ return res;
+ }
+
+ void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
+ DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
+ DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
+ mi.f <<= mi.e - pl.e;
+ mi.e = pl.e;
+ *plus = pl;
+ *minus = mi;
+ }
+
+ double ToDouble() const {
+ union {
+ double d;
+ uint64_t u64;
+ }u;
+ const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
+ static_cast<uint64_t>(e + kDpExponentBias);
+ u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
+ return u.d;
+ }
+
+ static const int kDiySignificandSize = 64;
+ static const int kDpSignificandSize = 52;
+ static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
+ static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
+ static const int kDpMinExponent = -kDpExponentBias;
+ static const int kDpDenormalExponent = -kDpExponentBias + 1;
+ static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+ static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+ static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+ uint64_t f;
+ int e;
+};
+
+inline DiyFp GetCachedPowerByIndex(size_t index) {
+ // 10^-348, 10^-340, ..., 10^340
+ static const uint64_t kCachedPowers_F[] = {
+ RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
+ RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
+ RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
+ RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
+ RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
+ RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
+ RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
+ RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
+ RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
+ RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
+ RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
+ RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
+ RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
+ RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
+ RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
+ RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
+ RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
+ RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
+ RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
+ RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
+ RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
+ RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
+ RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
+ RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
+ RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
+ RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
+ RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
+ RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
+ RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
+ RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
+ RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
+ RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
+ RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
+ RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
+ RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
+ RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
+ RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
+ RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
+ RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
+ RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
+ RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
+ RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
+ RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
+ RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
+ };
+ static const int16_t kCachedPowers_E[] = {
+ -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
+ -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
+ -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
+ -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
+ -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
+ 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
+ 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
+ 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
+ 907, 933, 960, 986, 1013, 1039, 1066
+ };
+ return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
+}
+
+inline DiyFp GetCachedPower(int e, int* K) {
+
+ //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
+ double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
+ int k = static_cast<int>(dk);
+ if (dk - k > 0.0)
+ k++;
+
+ unsigned index = static_cast<unsigned>((k >> 3) + 1);
+ *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
+
+ return GetCachedPowerByIndex(index);
+}
+
+inline DiyFp GetCachedPower10(int exp, int *outExp) {
+ unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
+ *outExp = -348 + static_cast<int>(index) * 8;
+ return GetCachedPowerByIndex(index);
+ }
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DIYFP_H_
diff --git a/include/rapidjson/internal/dtoa.h b/include/rapidjson/internal/dtoa.h
new file mode 100644
index 00000000..8d6350e6
--- /dev/null
+++ b/include/rapidjson/internal/dtoa.h
@@ -0,0 +1,245 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DTOA_
+#define RAPIDJSON_DTOA_
+
+#include "itoa.h" // GetDigitsLut()
+#include "diyfp.h"
+#include "ieee754.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
+#endif
+
+inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
+ while (rest < wp_w && delta - rest >= ten_kappa &&
+ (rest + ten_kappa < wp_w || /// closer
+ wp_w - rest > rest + ten_kappa - wp_w)) {
+ buffer[len - 1]--;
+ rest += ten_kappa;
+ }
+}
+
+inline unsigned CountDecimalDigit32(uint32_t n) {
+ // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
+ if (n < 10) return 1;
+ if (n < 100) return 2;
+ if (n < 1000) return 3;
+ if (n < 10000) return 4;
+ if (n < 100000) return 5;
+ if (n < 1000000) return 6;
+ if (n < 10000000) return 7;
+ if (n < 100000000) return 8;
+ // Will not reach 10 digits in DigitGen()
+ //if (n < 1000000000) return 9;
+ //return 10;
+ return 9;
+}
+
+inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
+ static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+ const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
+ const DiyFp wp_w = Mp - W;
+ uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
+ uint64_t p2 = Mp.f & (one.f - 1);
+ unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
+ *len = 0;
+
+ while (kappa > 0) {
+ uint32_t d = 0;
+ switch (kappa) {
+ case 9: d = p1 / 100000000; p1 %= 100000000; break;
+ case 8: d = p1 / 10000000; p1 %= 10000000; break;
+ case 7: d = p1 / 1000000; p1 %= 1000000; break;
+ case 6: d = p1 / 100000; p1 %= 100000; break;
+ case 5: d = p1 / 10000; p1 %= 10000; break;
+ case 4: d = p1 / 1000; p1 %= 1000; break;
+ case 3: d = p1 / 100; p1 %= 100; break;
+ case 2: d = p1 / 10; p1 %= 10; break;
+ case 1: d = p1; p1 = 0; break;
+ default:;
+ }
+ if (d || *len)
+ buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
+ kappa--;
+ uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
+ if (tmp <= delta) {
+ *K += kappa;
+ GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
+ return;
+ }
+ }
+
+ // kappa = 0
+ for (;;) {
+ p2 *= 10;
+ delta *= 10;
+ char d = static_cast<char>(p2 >> -one.e);
+ if (d || *len)
+ buffer[(*len)++] = static_cast<char>('0' + d);
+ p2 &= one.f - 1;
+ kappa--;
+ if (p2 < delta) {
+ *K += kappa;
+ int index = -static_cast<int>(kappa);
+ GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
+ return;
+ }
+ }
+}
+
+inline void Grisu2(double value, char* buffer, int* length, int* K) {
+ const DiyFp v(value);
+ DiyFp w_m, w_p;
+ v.NormalizedBoundaries(&w_m, &w_p);
+
+ const DiyFp c_mk = GetCachedPower(w_p.e, K);
+ const DiyFp W = v.Normalize() * c_mk;
+ DiyFp Wp = w_p * c_mk;
+ DiyFp Wm = w_m * c_mk;
+ Wm.f++;
+ Wp.f--;
+ DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
+}
+
+inline char* WriteExponent(int K, char* buffer) {
+ if (K < 0) {
+ *buffer++ = '-';
+ K = -K;
+ }
+
+ if (K >= 100) {
+ *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
+ K %= 100;
+ const char* d = GetDigitsLut() + K * 2;
+ *buffer++ = d[0];
+ *buffer++ = d[1];
+ }
+ else if (K >= 10) {
+ const char* d = GetDigitsLut() + K * 2;
+ *buffer++ = d[0];
+ *buffer++ = d[1];
+ }
+ else
+ *buffer++ = static_cast<char>('0' + static_cast<char>(K));
+
+ return buffer;
+}
+
+inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
+ const int kk = length + k; // 10^(kk-1) <= v < 10^kk
+
+ if (0 <= k && kk <= 21) {
+ // 1234e7 -> 12340000000
+ for (int i = length; i < kk; i++)
+ buffer[i] = '0';
+ buffer[kk] = '.';
+ buffer[kk + 1] = '0';
+ return &buffer[kk + 2];
+ }
+ else if (0 < kk && kk <= 21) {
+ // 1234e-2 -> 12.34
+ std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
+ buffer[kk] = '.';
+ if (0 > k + maxDecimalPlaces) {
+ // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
+ if (buffer[i] != '0')
+ return &buffer[i + 1];
+ return &buffer[kk + 2]; // Reserve one zero
+ }
+ else
+ return &buffer[length + 1];
+ }
+ else if (-6 < kk && kk <= 0) {
+ // 1234e-6 -> 0.001234
+ const int offset = 2 - kk;
+ std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
+ buffer[0] = '0';
+ buffer[1] = '.';
+ for (int i = 2; i < offset; i++)
+ buffer[i] = '0';
+ if (length - kk > maxDecimalPlaces) {
+ // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for (int i = maxDecimalPlaces + 1; i > 2; i--)
+ if (buffer[i] != '0')
+ return &buffer[i + 1];
+ return &buffer[3]; // Reserve one zero
+ }
+ else
+ return &buffer[length + offset];
+ }
+ else if (kk < -maxDecimalPlaces) {
+ // Truncate to zero
+ buffer[0] = '0';
+ buffer[1] = '.';
+ buffer[2] = '0';
+ return &buffer[3];
+ }
+ else if (length == 1) {
+ // 1e30
+ buffer[1] = 'e';
+ return WriteExponent(kk - 1, &buffer[2]);
+ }
+ else {
+ // 1234e30 -> 1.234e33
+ std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
+ buffer[1] = '.';
+ buffer[length + 1] = 'e';
+ return WriteExponent(kk - 1, &buffer[0 + length + 2]);
+ }
+}
+
+inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
+ RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
+ Double d(value);
+ if (d.IsZero()) {
+ if (d.Sign())
+ *buffer++ = '-'; // -0.0, Issue #289
+ buffer[0] = '0';
+ buffer[1] = '.';
+ buffer[2] = '0';
+ return &buffer[3];
+ }
+ else {
+ if (value < 0) {
+ *buffer++ = '-';
+ value = -value;
+ }
+ int length, K;
+ Grisu2(value, buffer, &length, &K);
+ return Prettify(buffer, length, K, maxDecimalPlaces);
+ }
+}
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DTOA_
diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h
new file mode 100644
index 00000000..82bb0b99
--- /dev/null
+++ b/include/rapidjson/internal/ieee754.h
@@ -0,0 +1,78 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_IEEE754_
+#define RAPIDJSON_IEEE754_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class Double {
+public:
+ Double() {}
+ Double(double d) : d_(d) {}
+ Double(uint64_t u) : u_(u) {}
+
+ double Value() const { return d_; }
+ uint64_t Uint64Value() const { return u_; }
+
+ double NextPositiveDouble() const {
+ RAPIDJSON_ASSERT(!Sign());
+ return Double(u_ + 1).Value();
+ }
+
+ bool Sign() const { return (u_ & kSignMask) != 0; }
+ uint64_t Significand() const { return u_ & kSignificandMask; }
+ int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
+
+ bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
+ bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
+ bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
+ bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
+ bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
+
+ uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
+ int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
+ uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
+
+ static unsigned EffectiveSignificandSize(int order) {
+ if (order >= -1021)
+ return 53;
+ else if (order <= -1074)
+ return 0;
+ else
+ return static_cast<unsigned>(order) + 1074;
+ }
+
+private:
+ static const int kSignificandSize = 52;
+ static const int kExponentBias = 0x3FF;
+ static const int kDenormalExponent = 1 - kExponentBias;
+ static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
+ static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+ static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+ static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+ union {
+ double d_;
+ uint64_t u_;
+ };
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_IEEE754_
diff --git a/include/rapidjson/internal/itoa.h b/include/rapidjson/internal/itoa.h
new file mode 100644
index 00000000..01a4e7e7
--- /dev/null
+++ b/include/rapidjson/internal/itoa.h
@@ -0,0 +1,304 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ITOA_
+#define RAPIDJSON_ITOA_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline const char* GetDigitsLut() {
+ static const char cDigitsLut[200] = {
+ '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
+ '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
+ '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
+ '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
+ '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
+ '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
+ '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
+ '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
+ '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
+ '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
+ };
+ return cDigitsLut;
+}
+
+inline char* u32toa(uint32_t value, char* buffer) {
+ const char* cDigitsLut = GetDigitsLut();
+
+ if (value < 10000) {
+ const uint32_t d1 = (value / 100) << 1;
+ const uint32_t d2 = (value % 100) << 1;
+
+ if (value >= 1000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 100)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 10)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ }
+ else if (value < 100000000) {
+ // value = bbbbcccc
+ const uint32_t b = value / 10000;
+ const uint32_t c = value % 10000;
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ if (value >= 10000000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 1000000)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 100000)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ else {
+ // value = aabbbbcccc in decimal
+
+ const uint32_t a = value / 100000000; // 1 to 42
+ value %= 100000000;
+
+ if (a >= 10) {
+ const unsigned i = a << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+
+ const uint32_t b = value / 10000; // 0 to 9999
+ const uint32_t c = value % 10000; // 0 to 9999
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ *buffer++ = cDigitsLut[d1];
+ *buffer++ = cDigitsLut[d1 + 1];
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ return buffer;
+}
+
+inline char* i32toa(int32_t value, char* buffer) {
+ uint32_t u = static_cast<uint32_t>(value);
+ if (value < 0) {
+ *buffer++ = '-';
+ u = ~u + 1;
+ }
+
+ return u32toa(u, buffer);
+}
+
+inline char* u64toa(uint64_t value, char* buffer) {
+ const char* cDigitsLut = GetDigitsLut();
+ const uint64_t kTen8 = 100000000;
+ const uint64_t kTen9 = kTen8 * 10;
+ const uint64_t kTen10 = kTen8 * 100;
+ const uint64_t kTen11 = kTen8 * 1000;
+ const uint64_t kTen12 = kTen8 * 10000;
+ const uint64_t kTen13 = kTen8 * 100000;
+ const uint64_t kTen14 = kTen8 * 1000000;
+ const uint64_t kTen15 = kTen8 * 10000000;
+ const uint64_t kTen16 = kTen8 * kTen8;
+
+ if (value < kTen8) {
+ uint32_t v = static_cast<uint32_t>(value);
+ if (v < 10000) {
+ const uint32_t d1 = (v / 100) << 1;
+ const uint32_t d2 = (v % 100) << 1;
+
+ if (v >= 1000)
+ *buffer++ = cDigitsLut[d1];
+ if (v >= 100)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (v >= 10)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ }
+ else {
+ // value = bbbbcccc
+ const uint32_t b = v / 10000;
+ const uint32_t c = v % 10000;
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ if (value >= 10000000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 1000000)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 100000)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ }
+ else if (value < kTen16) {
+ const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+ const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+
+ const uint32_t b0 = v0 / 10000;
+ const uint32_t c0 = v0 % 10000;
+
+ const uint32_t d1 = (b0 / 100) << 1;
+ const uint32_t d2 = (b0 % 100) << 1;
+
+ const uint32_t d3 = (c0 / 100) << 1;
+ const uint32_t d4 = (c0 % 100) << 1;
+
+ const uint32_t b1 = v1 / 10000;
+ const uint32_t c1 = v1 % 10000;
+
+ const uint32_t d5 = (b1 / 100) << 1;
+ const uint32_t d6 = (b1 % 100) << 1;
+
+ const uint32_t d7 = (c1 / 100) << 1;
+ const uint32_t d8 = (c1 % 100) << 1;
+
+ if (value >= kTen15)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= kTen14)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= kTen13)
+ *buffer++ = cDigitsLut[d2];
+ if (value >= kTen12)
+ *buffer++ = cDigitsLut[d2 + 1];
+ if (value >= kTen11)
+ *buffer++ = cDigitsLut[d3];
+ if (value >= kTen10)
+ *buffer++ = cDigitsLut[d3 + 1];
+ if (value >= kTen9)
+ *buffer++ = cDigitsLut[d4];
+ if (value >= kTen8)
+ *buffer++ = cDigitsLut[d4 + 1];
+
+ *buffer++ = cDigitsLut[d5];
+ *buffer++ = cDigitsLut[d5 + 1];
+ *buffer++ = cDigitsLut[d6];
+ *buffer++ = cDigitsLut[d6 + 1];
+ *buffer++ = cDigitsLut[d7];
+ *buffer++ = cDigitsLut[d7 + 1];
+ *buffer++ = cDigitsLut[d8];
+ *buffer++ = cDigitsLut[d8 + 1];
+ }
+ else {
+ const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
+ value %= kTen16;
+
+ if (a < 10)
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+ else if (a < 100) {
+ const uint32_t i = a << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else if (a < 1000) {
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
+
+ const uint32_t i = (a % 100) << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else {
+ const uint32_t i = (a / 100) << 1;
+ const uint32_t j = (a % 100) << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ *buffer++ = cDigitsLut[j];
+ *buffer++ = cDigitsLut[j + 1];
+ }
+
+ const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+ const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+
+ const uint32_t b0 = v0 / 10000;
+ const uint32_t c0 = v0 % 10000;
+
+ const uint32_t d1 = (b0 / 100) << 1;
+ const uint32_t d2 = (b0 % 100) << 1;
+
+ const uint32_t d3 = (c0 / 100) << 1;
+ const uint32_t d4 = (c0 % 100) << 1;
+
+ const uint32_t b1 = v1 / 10000;
+ const uint32_t c1 = v1 % 10000;
+
+ const uint32_t d5 = (b1 / 100) << 1;
+ const uint32_t d6 = (b1 % 100) << 1;
+
+ const uint32_t d7 = (c1 / 100) << 1;
+ const uint32_t d8 = (c1 % 100) << 1;
+
+ *buffer++ = cDigitsLut[d1];
+ *buffer++ = cDigitsLut[d1 + 1];
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ *buffer++ = cDigitsLut[d5];
+ *buffer++ = cDigitsLut[d5 + 1];
+ *buffer++ = cDigitsLut[d6];
+ *buffer++ = cDigitsLut[d6 + 1];
+ *buffer++ = cDigitsLut[d7];
+ *buffer++ = cDigitsLut[d7 + 1];
+ *buffer++ = cDigitsLut[d8];
+ *buffer++ = cDigitsLut[d8 + 1];
+ }
+
+ return buffer;
+}
+
+inline char* i64toa(int64_t value, char* buffer) {
+ uint64_t u = static_cast<uint64_t>(value);
+ if (value < 0) {
+ *buffer++ = '-';
+ u = ~u + 1;
+ }
+
+ return u64toa(u, buffer);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ITOA_
diff --git a/include/rapidjson/internal/meta.h b/include/rapidjson/internal/meta.h
new file mode 100644
index 00000000..5a9aaa42
--- /dev/null
+++ b/include/rapidjson/internal/meta.h
@@ -0,0 +1,181 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_META_H_
+#define RAPIDJSON_INTERNAL_META_H_
+
+#include "../rapidjson.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+#if defined(_MSC_VER)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(6334)
+#endif
+
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+#include <type_traits>
+#endif
+
+//@cond RAPIDJSON_INTERNAL
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
+template <typename T> struct Void { typedef void Type; };
+
+///////////////////////////////////////////////////////////////////////////////
+// BoolType, TrueType, FalseType
+//
+template <bool Cond> struct BoolType {
+ static const bool Value = Cond;
+ typedef BoolType Type;
+};
+typedef BoolType<true> TrueType;
+typedef BoolType<false> FalseType;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
+//
+
+template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
+template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
+template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
+template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
+
+template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
+template <> struct AndExprCond<true, true> : TrueType {};
+template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
+template <> struct OrExprCond<false, false> : FalseType {};
+
+template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
+template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
+template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
+template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// AddConst, MaybeAddConst, RemoveConst
+template <typename T> struct AddConst { typedef const T Type; };
+template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
+template <typename T> struct RemoveConst { typedef T Type; };
+template <typename T> struct RemoveConst<const T> { typedef T Type; };
+
+
+///////////////////////////////////////////////////////////////////////////////
+// IsSame, IsConst, IsMoreConst, IsPointer
+//
+template <typename T, typename U> struct IsSame : FalseType {};
+template <typename T> struct IsSame<T, T> : TrueType {};
+
+template <typename T> struct IsConst : FalseType {};
+template <typename T> struct IsConst<const T> : TrueType {};
+
+template <typename CT, typename T>
+struct IsMoreConst
+ : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
+ BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
+
+template <typename T> struct IsPointer : FalseType {};
+template <typename T> struct IsPointer<T*> : TrueType {};
+
+///////////////////////////////////////////////////////////////////////////////
+// IsBaseOf
+//
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+template <typename B, typename D> struct IsBaseOf
+ : BoolType< ::std::is_base_of<B,D>::value> {};
+
+#else // simplified version adopted from Boost
+
+template<typename B, typename D> struct IsBaseOfImpl {
+ RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
+ RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
+
+ typedef char (&Yes)[1];
+ typedef char (&No) [2];
+
+ template <typename T>
+ static Yes Check(const D*, T);
+ static No Check(const B*, int);
+
+ struct Host {
+ operator const B*() const;
+ operator const D*();
+ };
+
+ enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
+};
+
+template <typename B, typename D> struct IsBaseOf
+ : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
+
+#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+
+//////////////////////////////////////////////////////////////////////////
+// EnableIf / DisableIf
+//
+template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
+template <typename T> struct EnableIfCond<false, T> { /* empty */ };
+
+template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
+template <typename T> struct DisableIfCond<true, T> { /* empty */ };
+
+template <typename Condition, typename T = void>
+struct EnableIf : EnableIfCond<Condition::Value, T> {};
+
+template <typename Condition, typename T = void>
+struct DisableIf : DisableIfCond<Condition::Value, T> {};
+
+// SFINAE helpers
+struct SfinaeTag {};
+template <typename T> struct RemoveSfinaeTag;
+template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
+
+#define RAPIDJSON_REMOVEFPTR_(type) \
+ typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
+ < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
+
+#define RAPIDJSON_ENABLEIF(cond) \
+ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_DISABLEIF(cond) \
+ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
+ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond), \
+ RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
+ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond), \
+ RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+//@endcond
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_META_H_
diff --git a/include/rapidjson/internal/pow10.h b/include/rapidjson/internal/pow10.h
new file mode 100644
index 00000000..02f475d7
--- /dev/null
+++ b/include/rapidjson/internal/pow10.h
@@ -0,0 +1,55 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_POW10_
+#define RAPIDJSON_POW10_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Computes integer powers of 10 in double (10.0^n).
+/*! This function uses lookup table for fast and accurate results.
+ \param n non-negative exponent. Must <= 308.
+ \return 10.0^n
+*/
+inline double Pow10(int n) {
+ static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
+ 1e+0,
+ 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
+ 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
+ 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
+ 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
+ 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
+ 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
+ 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
+ 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
+ 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
+ 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
+ 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
+ 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
+ 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
+ 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
+ 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
+ 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
+ };
+ RAPIDJSON_ASSERT(n >= 0 && n <= 308);
+ return e[n];
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_POW10_
diff --git a/include/rapidjson/internal/regex.h b/include/rapidjson/internal/regex.h
new file mode 100644
index 00000000..422a5240
--- /dev/null
+++ b/include/rapidjson/internal/regex.h
@@ -0,0 +1,701 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_REGEX_H_
+#define RAPIDJSON_INTERNAL_REGEX_H_
+
+#include "../allocators.h"
+#include "../stream.h"
+#include "stack.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(implicit-fallthrough)
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+#ifndef RAPIDJSON_REGEX_VERBOSE
+#define RAPIDJSON_REGEX_VERBOSE 0
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericRegex
+
+static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
+static const SizeType kRegexInvalidRange = ~SizeType(0);
+
+//! Regular expression engine with subset of ECMAscript grammar.
+/*!
+ Supported regular expression syntax:
+ - \c ab Concatenation
+ - \c a|b Alternation
+ - \c a? Zero or one
+ - \c a* Zero or more
+ - \c a+ One or more
+ - \c a{3} Exactly 3 times
+ - \c a{3,} At least 3 times
+ - \c a{3,5} 3 to 5 times
+ - \c (ab) Grouping
+ - \c ^a At the beginning
+ - \c a$ At the end
+ - \c . Any character
+ - \c [abc] Character classes
+ - \c [a-c] Character class range
+ - \c [a-z0-9_] Character class combination
+ - \c [^abc] Negated character classes
+ - \c [^a-c] Negated character class range
+ - \c [\b] Backspace (U+0008)
+ - \c \\| \\\\ ... Escape characters
+ - \c \\f Form feed (U+000C)
+ - \c \\n Line feed (U+000A)
+ - \c \\r Carriage return (U+000D)
+ - \c \\t Tab (U+0009)
+ - \c \\v Vertical tab (U+000B)
+
+ \note This is a Thompson NFA engine, implemented with reference to
+ Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
+ https://swtch.com/~rsc/regexp/regexp1.html
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericRegex {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ GenericRegex(const Ch* source, Allocator* allocator = 0) :
+ states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
+ stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
+ {
+ GenericStringStream<Encoding> ss(source);
+ DecodedStream<GenericStringStream<Encoding> > ds(ss);
+ Parse(ds);
+ }
+
+ ~GenericRegex() {
+ Allocator::Free(stateSet_);
+ }
+
+ bool IsValid() const {
+ return root_ != kRegexInvalidState;
+ }
+
+ template <typename InputStream>
+ bool Match(InputStream& is) const {
+ return SearchWithAnchoring(is, true, true);
+ }
+
+ bool Match(const Ch* s) const {
+ GenericStringStream<Encoding> is(s);
+ return Match(is);
+ }
+
+ template <typename InputStream>
+ bool Search(InputStream& is) const {
+ return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
+ }
+
+ bool Search(const Ch* s) const {
+ GenericStringStream<Encoding> is(s);
+ return Search(is);
+ }
+
+private:
+ enum Operator {
+ kZeroOrOne,
+ kZeroOrMore,
+ kOneOrMore,
+ kConcatenation,
+ kAlternation,
+ kLeftParenthesis
+ };
+
+ static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.'
+ static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
+ static const unsigned kRangeNegationFlag = 0x80000000;
+
+ struct Range {
+ unsigned start; //
+ unsigned end;
+ SizeType next;
+ };
+
+ struct State {
+ SizeType out; //!< Equals to kInvalid for matching state
+ SizeType out1; //!< Equals to non-kInvalid for split
+ SizeType rangeStart;
+ unsigned codepoint;
+ };
+
+ struct Frag {
+ Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
+ SizeType start;
+ SizeType out; //!< link-list of all output states
+ SizeType minIndex;
+ };
+
+ template <typename SourceStream>
+ class DecodedStream {
+ public:
+ DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
+ unsigned Peek() { return codepoint_; }
+ unsigned Take() {
+ unsigned c = codepoint_;
+ if (c) // No further decoding when '\0'
+ Decode();
+ return c;
+ }
+
+ private:
+ void Decode() {
+ if (!Encoding::Decode(ss_, &codepoint_))
+ codepoint_ = 0;
+ }
+
+ SourceStream& ss_;
+ unsigned codepoint_;
+ };
+
+ State& GetState(SizeType index) {
+ RAPIDJSON_ASSERT(index < stateCount_);
+ return states_.template Bottom<State>()[index];
+ }
+
+ const State& GetState(SizeType index) const {
+ RAPIDJSON_ASSERT(index < stateCount_);
+ return states_.template Bottom<State>()[index];
+ }
+
+ Range& GetRange(SizeType index) {
+ RAPIDJSON_ASSERT(index < rangeCount_);
+ return ranges_.template Bottom<Range>()[index];
+ }
+
+ const Range& GetRange(SizeType index) const {
+ RAPIDJSON_ASSERT(index < rangeCount_);
+ return ranges_.template Bottom<Range>()[index];
+ }
+
+ template <typename InputStream>
+ void Parse(DecodedStream<InputStream>& ds) {
+ Allocator allocator;
+ Stack<Allocator> operandStack(&allocator, 256); // Frag
+ Stack<Allocator> operatorStack(&allocator, 256); // Operator
+ Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
+
+ *atomCountStack.template Push<unsigned>() = 0;
+
+ unsigned codepoint;
+ while (ds.Peek() != 0) {
+ switch (codepoint = ds.Take()) {
+ case '^':
+ anchorBegin_ = true;
+ break;
+
+ case '$':
+ anchorEnd_ = true;
+ break;
+
+ case '|':
+ while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+ *operatorStack.template Push<Operator>() = kAlternation;
+ *atomCountStack.template Top<unsigned>() = 0;
+ break;
+
+ case '(':
+ *operatorStack.template Push<Operator>() = kLeftParenthesis;
+ *atomCountStack.template Push<unsigned>() = 0;
+ break;
+
+ case ')':
+ while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+ if (operatorStack.Empty())
+ return;
+ operatorStack.template Pop<Operator>(1);
+ atomCountStack.template Pop<unsigned>(1);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '?':
+ if (!Eval(operandStack, kZeroOrOne))
+ return;
+ break;
+
+ case '*':
+ if (!Eval(operandStack, kZeroOrMore))
+ return;
+ break;
+
+ case '+':
+ if (!Eval(operandStack, kOneOrMore))
+ return;
+ break;
+
+ case '{':
+ {
+ unsigned n, m;
+ if (!ParseUnsigned(ds, &n))
+ return;
+
+ if (ds.Peek() == ',') {
+ ds.Take();
+ if (ds.Peek() == '}')
+ m = kInfinityQuantifier;
+ else if (!ParseUnsigned(ds, &m) || m < n)
+ return;
+ }
+ else
+ m = n;
+
+ if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
+ return;
+ ds.Take();
+ }
+ break;
+
+ case '.':
+ PushOperand(operandStack, kAnyCharacterClass);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '[':
+ {
+ SizeType range;
+ if (!ParseRange(ds, &range))
+ return;
+ SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
+ GetState(s).rangeStart = range;
+ *operandStack.template Push<Frag>() = Frag(s, s, s);
+ }
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '\\': // Escape character
+ if (!CharacterEscape(ds, &codepoint))
+ return; // Unsupported escape character
+ // fall through to default
+
+ default: // Pattern character
+ PushOperand(operandStack, codepoint);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ }
+ }
+
+ while (!operatorStack.Empty())
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+
+ // Link the operand to matching state.
+ if (operandStack.GetSize() == sizeof(Frag)) {
+ Frag* e = operandStack.template Pop<Frag>(1);
+ Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
+ root_ = e->start;
+
+#if RAPIDJSON_REGEX_VERBOSE
+ printf("root: %d\n", root_);
+ for (SizeType i = 0; i < stateCount_ ; i++) {
+ State& s = GetState(i);
+ printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
+ }
+ printf("\n");
+#endif
+ }
+
+ // Preallocate buffer for SearchWithAnchoring()
+ RAPIDJSON_ASSERT(stateSet_ == 0);
+ if (stateCount_ > 0) {
+ stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
+ state0_.template Reserve<SizeType>(stateCount_);
+ state1_.template Reserve<SizeType>(stateCount_);
+ }
+ }
+
+ SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
+ State* s = states_.template Push<State>();
+ s->out = out;
+ s->out1 = out1;
+ s->codepoint = codepoint;
+ s->rangeStart = kRegexInvalidRange;
+ return stateCount_++;
+ }
+
+ void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
+ SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
+ *operandStack.template Push<Frag>() = Frag(s, s, s);
+ }
+
+ void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
+ if (*atomCountStack.template Top<unsigned>())
+ *operatorStack.template Push<Operator>() = kConcatenation;
+ (*atomCountStack.template Top<unsigned>())++;
+ }
+
+ SizeType Append(SizeType l1, SizeType l2) {
+ SizeType old = l1;
+ while (GetState(l1).out != kRegexInvalidState)
+ l1 = GetState(l1).out;
+ GetState(l1).out = l2;
+ return old;
+ }
+
+ void Patch(SizeType l, SizeType s) {
+ for (SizeType next; l != kRegexInvalidState; l = next) {
+ next = GetState(l).out;
+ GetState(l).out = s;
+ }
+ }
+
+ bool Eval(Stack<Allocator>& operandStack, Operator op) {
+ switch (op) {
+ case kConcatenation:
+ RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
+ {
+ Frag e2 = *operandStack.template Pop<Frag>(1);
+ Frag e1 = *operandStack.template Pop<Frag>(1);
+ Patch(e1.out, e2.start);
+ *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
+ }
+ return true;
+
+ case kAlternation:
+ if (operandStack.GetSize() >= sizeof(Frag) * 2) {
+ Frag e2 = *operandStack.template Pop<Frag>(1);
+ Frag e1 = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(e1.start, e2.start, 0);
+ *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
+ return true;
+ }
+ return false;
+
+ case kZeroOrOne:
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
+ return true;
+ }
+ return false;
+
+ case kZeroOrMore:
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ Patch(e.out, s);
+ *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
+ return true;
+ }
+ return false;
+
+ default:
+ RAPIDJSON_ASSERT(op == kOneOrMore);
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ Patch(e.out, s);
+ *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
+ RAPIDJSON_ASSERT(n <= m);
+ RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
+
+ if (n == 0) {
+ if (m == 0) // a{0} not support
+ return false;
+ else if (m == kInfinityQuantifier)
+ Eval(operandStack, kZeroOrMore); // a{0,} -> a*
+ else {
+ Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
+ for (unsigned i = 0; i < m - 1; i++)
+ CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
+ for (unsigned i = 0; i < m - 1; i++)
+ Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
+ }
+ return true;
+ }
+
+ for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
+ CloneTopOperand(operandStack);
+
+ if (m == kInfinityQuantifier)
+ Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
+ else if (m > n) {
+ CloneTopOperand(operandStack); // a{3,5} -> a a a a
+ Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
+ for (unsigned i = n; i < m - 1; i++)
+ CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
+ for (unsigned i = n; i < m; i++)
+ Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
+ }
+
+ for (unsigned i = 0; i < n - 1; i++)
+ Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
+
+ return true;
+ }
+
+ static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
+
+ void CloneTopOperand(Stack<Allocator>& operandStack) {
+ const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
+ SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
+ State* s = states_.template Push<State>(count);
+ memcpy(s, &GetState(src.minIndex), count * sizeof(State));
+ for (SizeType j = 0; j < count; j++) {
+ if (s[j].out != kRegexInvalidState)
+ s[j].out += count;
+ if (s[j].out1 != kRegexInvalidState)
+ s[j].out1 += count;
+ }
+ *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
+ stateCount_ += count;
+ }
+
+ template <typename InputStream>
+ bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
+ unsigned r = 0;
+ if (ds.Peek() < '0' || ds.Peek() > '9')
+ return false;
+ while (ds.Peek() >= '0' && ds.Peek() <= '9') {
+ if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
+ return false; // overflow
+ r = r * 10 + (ds.Take() - '0');
+ }
+ *u = r;
+ return true;
+ }
+
+ template <typename InputStream>
+ bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
+ bool isBegin = true;
+ bool negate = false;
+ int step = 0;
+ SizeType start = kRegexInvalidRange;
+ SizeType current = kRegexInvalidRange;
+ unsigned codepoint;
+ while ((codepoint = ds.Take()) != 0) {
+ if (isBegin) {
+ isBegin = false;
+ if (codepoint == '^') {
+ negate = true;
+ continue;
+ }
+ }
+
+ switch (codepoint) {
+ case ']':
+ if (start == kRegexInvalidRange)
+ return false; // Error: nothing inside []
+ if (step == 2) { // Add trailing '-'
+ SizeType r = NewRange('-');
+ RAPIDJSON_ASSERT(current != kRegexInvalidRange);
+ GetRange(current).next = r;
+ }
+ if (negate)
+ GetRange(start).start |= kRangeNegationFlag;
+ *range = start;
+ return true;
+
+ case '\\':
+ if (ds.Peek() == 'b') {
+ ds.Take();
+ codepoint = 0x0008; // Escape backspace character
+ }
+ else if (!CharacterEscape(ds, &codepoint))
+ return false;
+ // fall through to default
+
+ default:
+ switch (step) {
+ case 1:
+ if (codepoint == '-') {
+ step++;
+ break;
+ }
+ // fall through to step 0 for other characters
+
+ case 0:
+ {
+ SizeType r = NewRange(codepoint);
+ if (current != kRegexInvalidRange)
+ GetRange(current).next = r;
+ if (start == kRegexInvalidRange)
+ start = r;
+ current = r;
+ }
+ step = 1;
+ break;
+
+ default:
+ RAPIDJSON_ASSERT(step == 2);
+ GetRange(current).end = codepoint;
+ step = 0;
+ }
+ }
+ }
+ return false;
+ }
+
+ SizeType NewRange(unsigned codepoint) {
+ Range* r = ranges_.template Push<Range>();
+ r->start = r->end = codepoint;
+ r->next = kRegexInvalidRange;
+ return rangeCount_++;
+ }
+
+ template <typename InputStream>
+ bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
+ unsigned codepoint;
+ switch (codepoint = ds.Take()) {
+ case '^':
+ case '$':
+ case '|':
+ case '(':
+ case ')':
+ case '?':
+ case '*':
+ case '+':
+ case '.':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ case '\\':
+ *escapedCodepoint = codepoint; return true;
+ case 'f': *escapedCodepoint = 0x000C; return true;
+ case 'n': *escapedCodepoint = 0x000A; return true;
+ case 'r': *escapedCodepoint = 0x000D; return true;
+ case 't': *escapedCodepoint = 0x0009; return true;
+ case 'v': *escapedCodepoint = 0x000B; return true;
+ default:
+ return false; // Unsupported escape character
+ }
+ }
+
+ template <typename InputStream>
+ bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
+ RAPIDJSON_ASSERT(IsValid());
+ DecodedStream<InputStream> ds(is);
+
+ state0_.Clear();
+ Stack<Allocator> *current = &state0_, *next = &state1_;
+ const size_t stateSetSize = GetStateSetSize();
+ std::memset(stateSet_, 0, stateSetSize);
+
+ bool matched = AddState(*current, root_);
+ unsigned codepoint;
+ while (!current->Empty() && (codepoint = ds.Take()) != 0) {
+ std::memset(stateSet_, 0, stateSetSize);
+ next->Clear();
+ matched = false;
+ for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
+ const State& sr = GetState(*s);
+ if (sr.codepoint == codepoint ||
+ sr.codepoint == kAnyCharacterClass ||
+ (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
+ {
+ matched = AddState(*next, sr.out) || matched;
+ if (!anchorEnd && matched)
+ return true;
+ }
+ if (!anchorBegin)
+ AddState(*next, root_);
+ }
+ internal::Swap(current, next);
+ }
+
+ return matched;
+ }
+
+ size_t GetStateSetSize() const {
+ return (stateCount_ + 31) / 32 * 4;
+ }
+
+ // Return whether the added states is a match state
+ bool AddState(Stack<Allocator>& l, SizeType index) const {
+ RAPIDJSON_ASSERT(index != kRegexInvalidState);
+
+ const State& s = GetState(index);
+ if (s.out1 != kRegexInvalidState) { // Split
+ bool matched = AddState(l, s.out);
+ return AddState(l, s.out1) || matched;
+ }
+ else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
+ stateSet_[index >> 5] |= (1 << (index & 31));
+ *l.template PushUnsafe<SizeType>() = index;
+ }
+ return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
+ }
+
+ bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
+ bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
+ while (rangeIndex != kRegexInvalidRange) {
+ const Range& r = GetRange(rangeIndex);
+ if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
+ return yes;
+ rangeIndex = r.next;
+ }
+ return !yes;
+ }
+
+ Stack<Allocator> states_;
+ Stack<Allocator> ranges_;
+ SizeType root_;
+ SizeType stateCount_;
+ SizeType rangeCount_;
+
+ static const unsigned kInfinityQuantifier = ~0u;
+
+ // For SearchWithAnchoring()
+ uint32_t* stateSet_; // allocated by states_.GetAllocator()
+ mutable Stack<Allocator> state0_;
+ mutable Stack<Allocator> state1_;
+ bool anchorBegin_;
+ bool anchorEnd_;
+};
+
+typedef GenericRegex<UTF8<> > Regex;
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_REGEX_H_
diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h
new file mode 100644
index 00000000..022c9aab
--- /dev/null
+++ b/include/rapidjson/internal/stack.h
@@ -0,0 +1,230 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_STACK_H_
+#define RAPIDJSON_INTERNAL_STACK_H_
+
+#include "../allocators.h"
+#include "swap.h"
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stack
+
+//! A type-unsafe stack for storing different types of data.
+/*! \tparam Allocator Allocator for allocating stack memory.
+*/
+template <typename Allocator>
+class Stack {
+public:
+ // Optimization note: Do not allocate memory for stack_ in constructor.
+ // Do it lazily when first Push() -> Expand() -> Resize().
+ Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Stack(Stack&& rhs)
+ : allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ stack_(rhs.stack_),
+ stackTop_(rhs.stackTop_),
+ stackEnd_(rhs.stackEnd_),
+ initialCapacity_(rhs.initialCapacity_)
+ {
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.stack_ = 0;
+ rhs.stackTop_ = 0;
+ rhs.stackEnd_ = 0;
+ rhs.initialCapacity_ = 0;
+ }
+#endif
+
+ ~Stack() {
+ Destroy();
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Stack& operator=(Stack&& rhs) {
+ if (&rhs != this)
+ {
+ Destroy();
+
+ allocator_ = rhs.allocator_;
+ ownAllocator_ = rhs.ownAllocator_;
+ stack_ = rhs.stack_;
+ stackTop_ = rhs.stackTop_;
+ stackEnd_ = rhs.stackEnd_;
+ initialCapacity_ = rhs.initialCapacity_;
+
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.stack_ = 0;
+ rhs.stackTop_ = 0;
+ rhs.stackEnd_ = 0;
+ rhs.initialCapacity_ = 0;
+ }
+ return *this;
+ }
+#endif
+
+ void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
+ internal::Swap(allocator_, rhs.allocator_);
+ internal::Swap(ownAllocator_, rhs.ownAllocator_);
+ internal::Swap(stack_, rhs.stack_);
+ internal::Swap(stackTop_, rhs.stackTop_);
+ internal::Swap(stackEnd_, rhs.stackEnd_);
+ internal::Swap(initialCapacity_, rhs.initialCapacity_);
+ }
+
+ void Clear() { stackTop_ = stack_; }
+
+ void ShrinkToFit() {
+ if (Empty()) {
+ // If the stack is empty, completely deallocate the memory.
+ Allocator::Free(stack_);
+ stack_ = 0;
+ stackTop_ = 0;
+ stackEnd_ = 0;
+ }
+ else
+ Resize(GetSize());
+ }
+
+ // Optimization note: try to minimize the size of this function for force inline.
+ // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
+ template<typename T>
+ RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
+ // Expand the stack if needed
+ if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
+ Expand<T>(count);
+ }
+
+ template<typename T>
+ RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
+ Reserve<T>(count);
+ return PushUnsafe<T>(count);
+ }
+
+ template<typename T>
+ RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
+ RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
+ T* ret = reinterpret_cast<T*>(stackTop_);
+ stackTop_ += sizeof(T) * count;
+ return ret;
+ }
+
+ template<typename T>
+ T* Pop(size_t count) {
+ RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
+ stackTop_ -= count * sizeof(T);
+ return reinterpret_cast<T*>(stackTop_);
+ }
+
+ template<typename T>
+ T* Top() {
+ RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+ return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+ }
+
+ template<typename T>
+ const T* Top() const {
+ RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+ return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+ }
+
+ template<typename T>
+ T* End() { return reinterpret_cast<T*>(stackTop_); }
+
+ template<typename T>
+ const T* End() const { return reinterpret_cast<T*>(stackTop_); }
+
+ template<typename T>
+ T* Bottom() { return reinterpret_cast<T*>(stack_); }
+
+ template<typename T>
+ const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
+
+ bool HasAllocator() const {
+ return allocator_ != 0;
+ }
+
+ Allocator& GetAllocator() {
+ RAPIDJSON_ASSERT(allocator_);
+ return *allocator_;
+ }
+
+ bool Empty() const { return stackTop_ == stack_; }
+ size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
+ size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
+
+private:
+ template<typename T>
+ void Expand(size_t count) {
+ // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
+ size_t newCapacity;
+ if (stack_ == 0) {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ newCapacity = initialCapacity_;
+ } else {
+ newCapacity = GetCapacity();
+ newCapacity += (newCapacity + 1) / 2;
+ }
+ size_t newSize = GetSize() + sizeof(T) * count;
+ if (newCapacity < newSize)
+ newCapacity = newSize;
+
+ Resize(newCapacity);
+ }
+
+ void Resize(size_t newCapacity) {
+ const size_t size = GetSize(); // Backup the current size
+ stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
+ stackTop_ = stack_ + size;
+ stackEnd_ = stack_ + newCapacity;
+ }
+
+ void Destroy() {
+ Allocator::Free(stack_);
+ RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
+ }
+
+ // Prohibit copy constructor & assignment operator.
+ Stack(const Stack&);
+ Stack& operator=(const Stack&);
+
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ char *stack_;
+ char *stackTop_;
+ char *stackEnd_;
+ size_t initialCapacity_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_STACK_H_
diff --git a/include/rapidjson/internal/strfunc.h b/include/rapidjson/internal/strfunc.h
new file mode 100644
index 00000000..2edfae52
--- /dev/null
+++ b/include/rapidjson/internal/strfunc.h
@@ -0,0 +1,55 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
+#define RAPIDJSON_INTERNAL_STRFUNC_H_
+
+#include "../stream.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom strlen() which works on different character types.
+/*! \tparam Ch Character type (e.g. char, wchar_t, short)
+ \param s Null-terminated input string.
+ \return Number of characters in the string.
+ \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
+*/
+template <typename Ch>
+inline SizeType StrLen(const Ch* s) {
+ const Ch* p = s;
+ while (*p) ++p;
+ return SizeType(p - s);
+}
+
+//! Returns number of code points in a encoded string.
+template<typename Encoding>
+bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
+ GenericStringStream<Encoding> is(s);
+ const typename Encoding::Ch* end = s + length;
+ SizeType count = 0;
+ while (is.src_ < end) {
+ unsigned codepoint;
+ if (!Encoding::Decode(is, &codepoint))
+ return false;
+ count++;
+ }
+ *outCount = count;
+ return true;
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
diff --git a/include/rapidjson/internal/strtod.h b/include/rapidjson/internal/strtod.h
new file mode 100644
index 00000000..289c413b
--- /dev/null
+++ b/include/rapidjson/internal/strtod.h
@@ -0,0 +1,269 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_STRTOD_
+#define RAPIDJSON_STRTOD_
+
+#include "ieee754.h"
+#include "biginteger.h"
+#include "diyfp.h"
+#include "pow10.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline double FastPath(double significand, int exp) {
+ if (exp < -308)
+ return 0.0;
+ else if (exp >= 0)
+ return significand * internal::Pow10(exp);
+ else
+ return significand / internal::Pow10(-exp);
+}
+
+inline double StrtodNormalPrecision(double d, int p) {
+ if (p < -308) {
+ // Prevent expSum < -308, making Pow10(p) = 0
+ d = FastPath(d, -308);
+ d = FastPath(d, p + 308);
+ }
+ else
+ d = FastPath(d, p);
+ return d;
+}
+
+template <typename T>
+inline T Min3(T a, T b, T c) {
+ T m = a;
+ if (m > b) m = b;
+ if (m > c) m = c;
+ return m;
+}
+
+inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
+ const Double db(b);
+ const uint64_t bInt = db.IntegerSignificand();
+ const int bExp = db.IntegerExponent();
+ const int hExp = bExp - 1;
+
+ int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
+
+ // Adjust for decimal exponent
+ if (dExp >= 0) {
+ dS_Exp2 += dExp;
+ dS_Exp5 += dExp;
+ }
+ else {
+ bS_Exp2 -= dExp;
+ bS_Exp5 -= dExp;
+ hS_Exp2 -= dExp;
+ hS_Exp5 -= dExp;
+ }
+
+ // Adjust for binary exponent
+ if (bExp >= 0)
+ bS_Exp2 += bExp;
+ else {
+ dS_Exp2 -= bExp;
+ hS_Exp2 -= bExp;
+ }
+
+ // Adjust for half ulp exponent
+ if (hExp >= 0)
+ hS_Exp2 += hExp;
+ else {
+ dS_Exp2 -= hExp;
+ bS_Exp2 -= hExp;
+ }
+
+ // Remove common power of two factor from all three scaled values
+ int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
+ dS_Exp2 -= common_Exp2;
+ bS_Exp2 -= common_Exp2;
+ hS_Exp2 -= common_Exp2;
+
+ BigInteger dS = d;
+ dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
+
+ BigInteger bS(bInt);
+ bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
+
+ BigInteger hS(1);
+ hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
+
+ BigInteger delta(0);
+ dS.Difference(bS, &delta);
+
+ return delta.Compare(hS);
+}
+
+inline bool StrtodFast(double d, int p, double* result) {
+ // Use fast path for string-to-double conversion if possible
+ // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
+ if (p > 22 && p < 22 + 16) {
+ // Fast Path Cases In Disguise
+ d *= internal::Pow10(p - 22);
+ p = 22;
+ }
+
+ if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
+ *result = FastPath(d, p);
+ return true;
+ }
+ else
+ return false;
+}
+
+// Compute an approximation and see if it is within 1/2 ULP
+inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
+ uint64_t significand = 0;
+ size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
+ for (; i < length; i++) {
+ if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
+ (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
+ break;
+ significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
+ }
+
+ if (i < length && decimals[i] >= '5') // Rounding
+ significand++;
+
+ size_t remaining = length - i;
+ const unsigned kUlpShift = 3;
+ const unsigned kUlp = 1 << kUlpShift;
+ int64_t error = (remaining == 0) ? 0 : kUlp / 2;
+
+ DiyFp v(significand, 0);
+ v = v.Normalize();
+ error <<= -v.e;
+
+ const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
+
+ int actualExp;
+ DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
+ if (actualExp != dExp) {
+ static const DiyFp kPow10[] = {
+ DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
+ DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
+ DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
+ DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
+ DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
+ DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
+ DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
+ };
+ int adjustment = dExp - actualExp - 1;
+ RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
+ v = v * kPow10[adjustment];
+ if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
+ error += kUlp / 2;
+ }
+
+ v = v * cachedPower;
+
+ error += kUlp + (error == 0 ? 0 : 1);
+
+ const int oldExp = v.e;
+ v = v.Normalize();
+ error <<= oldExp - v.e;
+
+ const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
+ unsigned precisionSize = 64 - effectiveSignificandSize;
+ if (precisionSize + kUlpShift >= 64) {
+ unsigned scaleExp = (precisionSize + kUlpShift) - 63;
+ v.f >>= scaleExp;
+ v.e += scaleExp;
+ error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
+ precisionSize -= scaleExp;
+ }
+
+ DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
+ const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
+ const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
+ if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
+ rounded.f++;
+ if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
+ rounded.f >>= 1;
+ rounded.e++;
+ }
+ }
+
+ *result = rounded.ToDouble();
+
+ return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
+}
+
+inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+ const BigInteger dInt(decimals, length);
+ const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
+ Double a(approx);
+ int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
+ if (cmp < 0)
+ return a.Value(); // within half ULP
+ else if (cmp == 0) {
+ // Round towards even
+ if (a.Significand() & 1)
+ return a.NextPositiveDouble();
+ else
+ return a.Value();
+ }
+ else // adjustment
+ return a.NextPositiveDouble();
+}
+
+inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+ RAPIDJSON_ASSERT(d >= 0.0);
+ RAPIDJSON_ASSERT(length >= 1);
+
+ double result;
+ if (StrtodFast(d, p, &result))
+ return result;
+
+ // Trim leading zeros
+ while (*decimals == '0' && length > 1) {
+ length--;
+ decimals++;
+ decimalPosition--;
+ }
+
+ // Trim trailing zeros
+ while (decimals[length - 1] == '0' && length > 1) {
+ length--;
+ decimalPosition--;
+ exp++;
+ }
+
+ // Trim right-most digits
+ const int kMaxDecimalDigit = 780;
+ if (static_cast<int>(length) > kMaxDecimalDigit) {
+ int delta = (static_cast<int>(length) - kMaxDecimalDigit);
+ exp += delta;
+ decimalPosition -= static_cast<unsigned>(delta);
+ length = kMaxDecimalDigit;
+ }
+
+ // If too small, underflow to zero
+ if (int(length) + exp < -324)
+ return 0.0;
+
+ if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
+ return result;
+
+ // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
+ return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRTOD_
diff --git a/include/rapidjson/internal/swap.h b/include/rapidjson/internal/swap.h
new file mode 100644
index 00000000..666e49f9
--- /dev/null
+++ b/include/rapidjson/internal/swap.h
@@ -0,0 +1,46 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_SWAP_H_
+#define RAPIDJSON_INTERNAL_SWAP_H_
+
+#include "../rapidjson.h"
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom swap() to avoid dependency on C++ <algorithm> header
+/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
+ \note This has the same semantics as std::swap().
+*/
+template <typename T>
+inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_SWAP_H_
diff --git a/include/rapidjson/istreamwrapper.h b/include/rapidjson/istreamwrapper.h
new file mode 100644
index 00000000..f5fe2897
--- /dev/null
+++ b/include/rapidjson/istreamwrapper.h
@@ -0,0 +1,115 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ISTREAMWRAPPER_H_
+#define RAPIDJSON_ISTREAMWRAPPER_H_
+
+#include "stream.h"
+#include <iosfwd>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
+/*!
+ The classes can be wrapped including but not limited to:
+
+ - \c std::istringstream
+ - \c std::stringstream
+ - \c std::wistringstream
+ - \c std::wstringstream
+ - \c std::ifstream
+ - \c std::fstream
+ - \c std::wifstream
+ - \c std::wfstream
+
+ \tparam StreamType Class derived from \c std::basic_istream.
+*/
+
+template <typename StreamType>
+class BasicIStreamWrapper {
+public:
+ typedef typename StreamType::char_type Ch;
+ BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
+
+ Ch Peek() const {
+ typename StreamType::int_type c = stream_.peek();
+ return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
+ }
+
+ Ch Take() {
+ typename StreamType::int_type c = stream_.get();
+ if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
+ count_++;
+ return static_cast<Ch>(c);
+ }
+ else
+ return '\0';
+ }
+
+ // tellg() may return -1 when failed. So we count by ourself.
+ size_t Tell() const { return count_; }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ // For encoding detection only.
+ const Ch* Peek4() const {
+ RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
+ int i;
+ bool hasError = false;
+ for (i = 0; i < 4; ++i) {
+ typename StreamType::int_type c = stream_.get();
+ if (c == StreamType::traits_type::eof()) {
+ hasError = true;
+ stream_.clear();
+ break;
+ }
+ peekBuffer_[i] = static_cast<Ch>(c);
+ }
+ for (--i; i >= 0; --i)
+ stream_.putback(peekBuffer_[i]);
+ return !hasError ? peekBuffer_ : 0;
+ }
+
+private:
+ BasicIStreamWrapper(const BasicIStreamWrapper&);
+ BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
+
+ StreamType& stream_;
+ size_t count_; //!< Number of characters read. Note:
+ mutable Ch peekBuffer_[4];
+};
+
+typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
+typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
+
+#if defined(__clang__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ISTREAMWRAPPER_H_
diff --git a/include/rapidjson/memorybuffer.h b/include/rapidjson/memorybuffer.h
new file mode 100644
index 00000000..39bee1de
--- /dev/null
+++ b/include/rapidjson/memorybuffer.h
@@ -0,0 +1,70 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_MEMORYBUFFER_H_
+#define RAPIDJSON_MEMORYBUFFER_H_
+
+#include "stream.h"
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output byte stream.
+/*!
+ This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.
+
+ It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
+
+ Differences between MemoryBuffer and StringBuffer:
+ 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer.
+ 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
+
+ \tparam Allocator type for allocating memory buffer.
+ \note implements Stream concept
+*/
+template <typename Allocator = CrtAllocator>
+struct GenericMemoryBuffer {
+ typedef char Ch; // byte
+
+ GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+ void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+ void Flush() {}
+
+ void Clear() { stack_.Clear(); }
+ void ShrinkToFit() { stack_.ShrinkToFit(); }
+ Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+ void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+ const Ch* GetBuffer() const {
+ return stack_.template Bottom<Ch>();
+ }
+
+ size_t GetSize() const { return stack_.GetSize(); }
+
+ static const size_t kDefaultCapacity = 256;
+ mutable internal::Stack<Allocator> stack_;
+};
+
+typedef GenericMemoryBuffer<> MemoryBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
+ std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/include/rapidjson/memorystream.h b/include/rapidjson/memorystream.h
new file mode 100644
index 00000000..1d71d8a4
--- /dev/null
+++ b/include/rapidjson/memorystream.h
@@ -0,0 +1,71 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_MEMORYSTREAM_H_
+#define RAPIDJSON_MEMORYSTREAM_H_
+
+#include "stream.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(unreachable-code)
+RAPIDJSON_DIAG_OFF(missing-noreturn)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory input byte stream.
+/*!
+ This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.
+
+ It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.
+
+ Differences between MemoryStream and StringStream:
+ 1. StringStream has encoding but MemoryStream is a byte stream.
+ 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.
+ 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
+ \note implements Stream concept
+*/
+struct MemoryStream {
+ typedef char Ch; // byte
+
+ MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
+
+ Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
+ Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
+ size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ // For encoding detection only.
+ const Ch* Peek4() const {
+ return Tell() + 4 <= size_ ? src_ : 0;
+ }
+
+ const Ch* src_; //!< Current read position.
+ const Ch* begin_; //!< Original head of the string.
+ const Ch* end_; //!< End of stream.
+ size_t size_; //!< Size of the stream.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/include/rapidjson/msinttypes/inttypes.h b/include/rapidjson/msinttypes/inttypes.h
new file mode 100644
index 00000000..18111286
--- /dev/null
+++ b/include/rapidjson/msinttypes/inttypes.h
@@ -0,0 +1,316 @@
+// ISO C9x compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2013 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the product nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// The above software in this distribution may have been modified by
+// THL A29 Limited ("Tencent Modifications").
+// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// miloyip: VC supports inttypes.h since VC2013
+#if _MSC_VER >= 1800
+#include <inttypes.h>
+#else
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+ intmax_t quot;
+ intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8 "d"
+#define PRIi8 "i"
+#define PRIdLEAST8 "d"
+#define PRIiLEAST8 "i"
+#define PRIdFAST8 "d"
+#define PRIiFAST8 "i"
+
+#define PRId16 "hd"
+#define PRIi16 "hi"
+#define PRIdLEAST16 "hd"
+#define PRIiLEAST16 "hi"
+#define PRIdFAST16 "hd"
+#define PRIiFAST16 "hi"
+
+#define PRId32 "I32d"
+#define PRIi32 "I32i"
+#define PRIdLEAST32 "I32d"
+#define PRIiLEAST32 "I32i"
+#define PRIdFAST32 "I32d"
+#define PRIiFAST32 "I32i"
+
+#define PRId64 "I64d"
+#define PRIi64 "I64i"
+#define PRIdLEAST64 "I64d"
+#define PRIiLEAST64 "I64i"
+#define PRIdFAST64 "I64d"
+#define PRIiFAST64 "I64i"
+
+#define PRIdMAX "I64d"
+#define PRIiMAX "I64i"
+
+#define PRIdPTR "Id"
+#define PRIiPTR "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8 "o"
+#define PRIu8 "u"
+#define PRIx8 "x"
+#define PRIX8 "X"
+#define PRIoLEAST8 "o"
+#define PRIuLEAST8 "u"
+#define PRIxLEAST8 "x"
+#define PRIXLEAST8 "X"
+#define PRIoFAST8 "o"
+#define PRIuFAST8 "u"
+#define PRIxFAST8 "x"
+#define PRIXFAST8 "X"
+
+#define PRIo16 "ho"
+#define PRIu16 "hu"
+#define PRIx16 "hx"
+#define PRIX16 "hX"
+#define PRIoLEAST16 "ho"
+#define PRIuLEAST16 "hu"
+#define PRIxLEAST16 "hx"
+#define PRIXLEAST16 "hX"
+#define PRIoFAST16 "ho"
+#define PRIuFAST16 "hu"
+#define PRIxFAST16 "hx"
+#define PRIXFAST16 "hX"
+
+#define PRIo32 "I32o"
+#define PRIu32 "I32u"
+#define PRIx32 "I32x"
+#define PRIX32 "I32X"
+#define PRIoLEAST32 "I32o"
+#define PRIuLEAST32 "I32u"
+#define PRIxLEAST32 "I32x"
+#define PRIXLEAST32 "I32X"
+#define PRIoFAST32 "I32o"
+#define PRIuFAST32 "I32u"
+#define PRIxFAST32 "I32x"
+#define PRIXFAST32 "I32X"
+
+#define PRIo64 "I64o"
+#define PRIu64 "I64u"
+#define PRIx64 "I64x"
+#define PRIX64 "I64X"
+#define PRIoLEAST64 "I64o"
+#define PRIuLEAST64 "I64u"
+#define PRIxLEAST64 "I64x"
+#define PRIXLEAST64 "I64X"
+#define PRIoFAST64 "I64o"
+#define PRIuFAST64 "I64u"
+#define PRIxFAST64 "I64x"
+#define PRIXFAST64 "I64X"
+
+#define PRIoMAX "I64o"
+#define PRIuMAX "I64u"
+#define PRIxMAX "I64x"
+#define PRIXMAX "I64X"
+
+#define PRIoPTR "Io"
+#define PRIuPTR "Iu"
+#define PRIxPTR "Ix"
+#define PRIXPTR "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8 "d"
+#define SCNi8 "i"
+#define SCNdLEAST8 "d"
+#define SCNiLEAST8 "i"
+#define SCNdFAST8 "d"
+#define SCNiFAST8 "i"
+
+#define SCNd16 "hd"
+#define SCNi16 "hi"
+#define SCNdLEAST16 "hd"
+#define SCNiLEAST16 "hi"
+#define SCNdFAST16 "hd"
+#define SCNiFAST16 "hi"
+
+#define SCNd32 "ld"
+#define SCNi32 "li"
+#define SCNdLEAST32 "ld"
+#define SCNiLEAST32 "li"
+#define SCNdFAST32 "ld"
+#define SCNiFAST32 "li"
+
+#define SCNd64 "I64d"
+#define SCNi64 "I64i"
+#define SCNdLEAST64 "I64d"
+#define SCNiLEAST64 "I64i"
+#define SCNdFAST64 "I64d"
+#define SCNiFAST64 "I64i"
+
+#define SCNdMAX "I64d"
+#define SCNiMAX "I64i"
+
+#ifdef _WIN64 // [
+# define SCNdPTR "I64d"
+# define SCNiPTR "I64i"
+#else // _WIN64 ][
+# define SCNdPTR "ld"
+# define SCNiPTR "li"
+#endif // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8 "o"
+#define SCNu8 "u"
+#define SCNx8 "x"
+#define SCNX8 "X"
+#define SCNoLEAST8 "o"
+#define SCNuLEAST8 "u"
+#define SCNxLEAST8 "x"
+#define SCNXLEAST8 "X"
+#define SCNoFAST8 "o"
+#define SCNuFAST8 "u"
+#define SCNxFAST8 "x"
+#define SCNXFAST8 "X"
+
+#define SCNo16 "ho"
+#define SCNu16 "hu"
+#define SCNx16 "hx"
+#define SCNX16 "hX"
+#define SCNoLEAST16 "ho"
+#define SCNuLEAST16 "hu"
+#define SCNxLEAST16 "hx"
+#define SCNXLEAST16 "hX"
+#define SCNoFAST16 "ho"
+#define SCNuFAST16 "hu"
+#define SCNxFAST16 "hx"
+#define SCNXFAST16 "hX"
+
+#define SCNo32 "lo"
+#define SCNu32 "lu"
+#define SCNx32 "lx"
+#define SCNX32 "lX"
+#define SCNoLEAST32 "lo"
+#define SCNuLEAST32 "lu"
+#define SCNxLEAST32 "lx"
+#define SCNXLEAST32 "lX"
+#define SCNoFAST32 "lo"
+#define SCNuFAST32 "lu"
+#define SCNxFAST32 "lx"
+#define SCNXFAST32 "lX"
+
+#define SCNo64 "I64o"
+#define SCNu64 "I64u"
+#define SCNx64 "I64x"
+#define SCNX64 "I64X"
+#define SCNoLEAST64 "I64o"
+#define SCNuLEAST64 "I64u"
+#define SCNxLEAST64 "I64x"
+#define SCNXLEAST64 "I64X"
+#define SCNoFAST64 "I64o"
+#define SCNuFAST64 "I64u"
+#define SCNxFAST64 "I64x"
+#define SCNXFAST64 "I64X"
+
+#define SCNoMAX "I64o"
+#define SCNuMAX "I64u"
+#define SCNxMAX "I64x"
+#define SCNXMAX "I64X"
+
+#ifdef _WIN64 // [
+# define SCNoPTR "I64o"
+# define SCNuPTR "I64u"
+# define SCNxPTR "I64x"
+# define SCNXPTR "I64X"
+#else // _WIN64 ][
+# define SCNoPTR "lo"
+# define SCNuPTR "lu"
+# define SCNxPTR "lx"
+# define SCNXPTR "lX"
+#endif // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+ imaxdiv_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ if (numer < 0 && result.rem > 0) {
+ // did division wrong; must fix up
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+#endif // _MSC_VER >= 1800
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/include/rapidjson/msinttypes/stdint.h b/include/rapidjson/msinttypes/stdint.h
new file mode 100644
index 00000000..3d4477b9
--- /dev/null
+++ b/include/rapidjson/msinttypes/stdint.h
@@ -0,0 +1,300 @@
+// ISO C9x compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2013 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the product nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// The above software in this distribution may have been modified by
+// THL A29 Limited ("Tencent Modifications").
+// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
+#if _MSC_VER >= 1600 // [
+#include <stdint.h>
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+#undef INT8_C
+#undef INT16_C
+#undef INT32_C
+#undef INT64_C
+#undef UINT8_C
+#undef UINT16_C
+#undef UINT32_C
+#undef UINT64_C
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C // [
+# define INTMAX_C INT64_C
+#endif // INTMAX_C ]
+#ifndef UINTMAX_C // [
+# define UINTMAX_C UINT64_C
+#endif // UINTMAX_C ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#else // ] _MSC_VER >= 1700 [
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler would give many errors like this:
+// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#if defined(__cplusplus) && !defined(_M_ARM)
+extern "C" {
+#endif
+# include <wchar.h>
+#if defined(__cplusplus) && !defined(_M_ARM)
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+# define _W64 __w64
+# else
+# define _W64
+# endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+#else
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+#endif
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+ typedef signed __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+#else // _WIN64 ][
+ typedef _W64 signed int intptr_t;
+ typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN ((int8_t)_I8_MIN)
+#define INT8_MAX _I8_MAX
+#define INT16_MIN ((int16_t)_I16_MIN)
+#define INT16_MAX _I16_MAX
+#define INT32_MIN ((int32_t)_I32_MIN)
+#define INT32_MAX _I32_MAX
+#define INT64_MIN ((int64_t)_I64_MIN)
+#define INT64_MAX _I64_MAX
+#define UINT8_MAX _UI8_MAX
+#define UINT16_MAX _UI16_MAX
+#define UINT32_MAX _UI32_MAX
+#define UINT64_MAX _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+# define INTPTR_MIN INT64_MIN
+# define INTPTR_MAX INT64_MAX
+# define UINTPTR_MAX UINT64_MAX
+#else // _WIN64 ][
+# define INTPTR_MIN INT32_MIN
+# define INTPTR_MAX INT32_MAX
+# define UINTPTR_MAX UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+# define PTRDIFF_MIN _I64_MIN
+# define PTRDIFF_MAX _I64_MAX
+#else // _WIN64 ][
+# define PTRDIFF_MIN _I32_MIN
+# define PTRDIFF_MAX _I32_MAX
+#endif // _WIN64 ]
+
+#define SIG_ATOMIC_MIN INT_MIN
+#define SIG_ATOMIC_MAX INT_MAX
+
+#ifndef SIZE_MAX // [
+# ifdef _WIN64 // [
+# define SIZE_MAX _UI64_MAX
+# else // _WIN64 ][
+# define SIZE_MAX _UI32_MAX
+# endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+# define WCHAR_MIN 0
+#endif // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+# define WCHAR_MAX _UI16_MAX
+#endif // WCHAR_MAX ]
+
+#define WINT_MIN 0
+#define WINT_MAX _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C // [
+# define INTMAX_C INT64_C
+#endif // INTMAX_C ]
+#ifndef UINTMAX_C // [
+# define UINTMAX_C UINT64_C
+#endif // UINTMAX_C ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#endif // _MSC_VER >= 1600 ]
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/include/rapidjson/ostreamwrapper.h b/include/rapidjson/ostreamwrapper.h
new file mode 100644
index 00000000..6f4667c0
--- /dev/null
+++ b/include/rapidjson/ostreamwrapper.h
@@ -0,0 +1,81 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_OSTREAMWRAPPER_H_
+#define RAPIDJSON_OSTREAMWRAPPER_H_
+
+#include "stream.h"
+#include <iosfwd>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept.
+/*!
+ The classes can be wrapped including but not limited to:
+
+ - \c std::ostringstream
+ - \c std::stringstream
+ - \c std::wpstringstream
+ - \c std::wstringstream
+ - \c std::ifstream
+ - \c std::fstream
+ - \c std::wofstream
+ - \c std::wfstream
+
+ \tparam StreamType Class derived from \c std::basic_ostream.
+*/
+
+template <typename StreamType>
+class BasicOStreamWrapper {
+public:
+ typedef typename StreamType::char_type Ch;
+ BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}
+
+ void Put(Ch c) {
+ stream_.put(c);
+ }
+
+ void Flush() {
+ stream_.flush();
+ }
+
+ // Not implemented
+ char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
+ char Take() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ BasicOStreamWrapper(const BasicOStreamWrapper&);
+ BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);
+
+ StreamType& stream_;
+};
+
+typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
+typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_OSTREAMWRAPPER_H_
diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h
new file mode 100644
index 00000000..0206ac1c
--- /dev/null
+++ b/include/rapidjson/pointer.h
@@ -0,0 +1,1358 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_POINTER_H_
+#define RAPIDJSON_POINTER_H_
+
+#include "document.h"
+#include "internal/itoa.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(switch-enum)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
+
+//! Error code of parsing.
+/*! \ingroup RAPIDJSON_ERRORS
+ \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
+*/
+enum PointerParseErrorCode {
+ kPointerParseErrorNone = 0, //!< The parse is successful
+
+ kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
+ kPointerParseErrorInvalidEscape, //!< Invalid escape
+ kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
+ kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericPointer
+
+//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
+/*!
+ This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
+ (https://tools.ietf.org/html/rfc6901).
+
+ A JSON pointer is for identifying a specific value in a JSON document
+ (GenericDocument). It can simplify coding of DOM tree manipulation, because it
+ can access multiple-level depth of DOM tree with single API call.
+
+ After it parses a string representation (e.g. "/foo/0" or URI fragment
+ representation (e.g. "#/foo/0") into its internal representation (tokens),
+ it can be used to resolve a specific value in multiple documents, or sub-tree
+ of documents.
+
+ Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
+ Apart from assignment, a Pointer cannot be modified after construction.
+
+ Although Pointer is very convenient, please aware that constructing Pointer
+ involves parsing and dynamic memory allocation. A special constructor with user-
+ supplied tokens eliminates these.
+
+ GenericPointer depends on GenericDocument and GenericValue.
+
+ \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
+ \tparam Allocator The allocator type for allocating memory for internal representation.
+
+ \note GenericPointer uses same encoding of ValueType.
+ However, Allocator of GenericPointer is independent of Allocator of Value.
+*/
+template <typename ValueType, typename Allocator = CrtAllocator>
+class GenericPointer {
+public:
+ typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
+ typedef typename ValueType::Ch Ch; //!< Character type from Value
+
+ //! A token is the basic units of internal representation.
+ /*!
+ A JSON pointer string representation "/foo/123" is parsed to two tokens:
+ "foo" and 123. 123 will be represented in both numeric form and string form.
+ They are resolved according to the actual value type (object or array).
+
+ For token that are not numbers, or the numeric value is out of bound
+ (greater than limits of SizeType), they are only treated as string form
+ (i.e. the token's index will be equal to kPointerInvalidIndex).
+
+ This struct is public so that user can create a Pointer without parsing and
+ allocation, using a special constructor.
+ */
+ struct Token {
+ const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character.
+ SizeType length; //!< Length of the name.
+ SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex.
+ };
+
+ //!@name Constructors and destructor.
+ //@{
+
+ //! Default constructor.
+ GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
+
+ //! Constructor that parses a string or URI fragment representation.
+ /*!
+ \param source A null-terminated, string or URI fragment representation of JSON pointer.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ */
+ explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source, internal::StrLen(source));
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Constructor that parses a string or URI fragment representation.
+ /*!
+ \param source A string or URI fragment representation of JSON pointer.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source.c_str(), source.size());
+ }
+#endif
+
+ //! Constructor that parses a string or URI fragment representation, with length of the source string.
+ /*!
+ \param source A string or URI fragment representation of JSON pointer.
+ \param length Length of source.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ \note Slightly faster than the overload without length.
+ */
+ GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source, length);
+ }
+
+ //! Constructor with user-supplied tokens.
+ /*!
+ This constructor let user supplies const array of tokens.
+ This prevents the parsing process and eliminates allocation.
+ This is preferred for memory constrained environments.
+
+ \param tokens An constant array of tokens representing the JSON pointer.
+ \param tokenCount Number of tokens.
+
+ \b Example
+ \code
+ #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
+ #define INDEX(i) { #i, sizeof(#i) - 1, i }
+
+ static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) };
+ static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
+ // Equivalent to static const Pointer p("/foo/123");
+
+ #undef NAME
+ #undef INDEX
+ \endcode
+ */
+ GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
+
+ //! Copy constructor.
+ GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ *this = rhs;
+ }
+
+ //! Destructor.
+ ~GenericPointer() {
+ if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
+ Allocator::Free(tokens_);
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ //! Assignment operator.
+ GenericPointer& operator=(const GenericPointer& rhs) {
+ if (this != &rhs) {
+ // Do not delete ownAllcator
+ if (nameBuffer_)
+ Allocator::Free(tokens_);
+
+ tokenCount_ = rhs.tokenCount_;
+ parseErrorOffset_ = rhs.parseErrorOffset_;
+ parseErrorCode_ = rhs.parseErrorCode_;
+
+ if (rhs.nameBuffer_)
+ CopyFromRaw(rhs); // Normally parsed tokens.
+ else {
+ tokens_ = rhs.tokens_; // User supplied const tokens.
+ nameBuffer_ = 0;
+ }
+ }
+ return *this;
+ }
+
+ //@}
+
+ //!@name Append token
+ //@{
+
+ //! Append a token and return a new Pointer
+ /*!
+ \param token Token to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
+ GenericPointer r;
+ r.allocator_ = allocator;
+ Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
+ std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
+ r.tokens_[tokenCount_].name = p;
+ r.tokens_[tokenCount_].length = token.length;
+ r.tokens_[tokenCount_].index = token.index;
+ return r;
+ }
+
+ //! Append a name token with length, and return a new Pointer
+ /*!
+ \param name Name to be appended.
+ \param length Length of name.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
+ Token token = { name, length, kPointerInvalidIndex };
+ return Append(token, allocator);
+ }
+
+ //! Append a name token without length, and return a new Pointer
+ /*!
+ \param name Name (const Ch*) to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
+ Append(T* name, Allocator* allocator = 0) const {
+ return Append(name, StrLen(name), allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Append a name token, and return a new Pointer
+ /*!
+ \param name Name to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
+ return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
+ }
+#endif
+
+ //! Append a index token, and return a new Pointer
+ /*!
+ \param index Index to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
+ char buffer[21];
+ char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
+ SizeType length = static_cast<SizeType>(end - buffer);
+ buffer[length] = '\0';
+
+ if (sizeof(Ch) == 1) {
+ Token token = { reinterpret_cast<Ch*>(buffer), length, index };
+ return Append(token, allocator);
+ }
+ else {
+ Ch name[21];
+ for (size_t i = 0; i <= length; i++)
+ name[i] = buffer[i];
+ Token token = { name, length, index };
+ return Append(token, allocator);
+ }
+ }
+
+ //! Append a token by value, and return a new Pointer
+ /*!
+ \param token token to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
+ if (token.IsString())
+ return Append(token.GetString(), token.GetStringLength(), allocator);
+ else {
+ RAPIDJSON_ASSERT(token.IsUint64());
+ RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
+ return Append(static_cast<SizeType>(token.GetUint64()), allocator);
+ }
+ }
+
+ //!@name Handling Parse Error
+ //@{
+
+ //! Check whether this is a valid pointer.
+ bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
+
+ //! Get the parsing error offset in code unit.
+ size_t GetParseErrorOffset() const { return parseErrorOffset_; }
+
+ //! Get the parsing error code.
+ PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
+
+ //@}
+
+ //! Get the allocator of this pointer.
+ Allocator& GetAllocator() { return *allocator_; }
+
+ //!@name Tokens
+ //@{
+
+ //! Get the token array (const version only).
+ const Token* GetTokens() const { return tokens_; }
+
+ //! Get the number of tokens.
+ size_t GetTokenCount() const { return tokenCount_; }
+
+ //@}
+
+ //!@name Equality/inequality operators
+ //@{
+
+ //! Equality operator.
+ /*!
+ \note When any pointers are invalid, always returns false.
+ */
+ bool operator==(const GenericPointer& rhs) const {
+ if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
+ return false;
+
+ for (size_t i = 0; i < tokenCount_; i++) {
+ if (tokens_[i].index != rhs.tokens_[i].index ||
+ tokens_[i].length != rhs.tokens_[i].length ||
+ (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //! Inequality operator.
+ /*!
+ \note When any pointers are invalid, always returns true.
+ */
+ bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
+
+ //@}
+
+ //!@name Stringify
+ //@{
+
+ //! Stringify the pointer into string representation.
+ /*!
+ \tparam OutputStream Type of output stream.
+ \param os The output stream.
+ */
+ template<typename OutputStream>
+ bool Stringify(OutputStream& os) const {
+ return Stringify<false, OutputStream>(os);
+ }
+
+ //! Stringify the pointer into URI fragment representation.
+ /*!
+ \tparam OutputStream Type of output stream.
+ \param os The output stream.
+ */
+ template<typename OutputStream>
+ bool StringifyUriFragment(OutputStream& os) const {
+ return Stringify<true, OutputStream>(os);
+ }
+
+ //@}
+
+ //!@name Create value
+ //@{
+
+ //! Create a value in a subtree.
+ /*!
+ If the value is not exist, it creates all parent values and a JSON Null value.
+ So it always succeed and return the newly created or existing value.
+
+ Remind that it may change types of parents according to tokens, so it
+ potentially removes previously stored values. For example, if a document
+ was an array, and "/foo" is used to create a value, then the document
+ will be changed to an object, and all existing array elements are lost.
+
+ \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \param alreadyExist If non-null, it stores whether the resolved value is already exist.
+ \return The resolved newly created (a JSON Null value), or already exists value.
+ */
+ ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
+ RAPIDJSON_ASSERT(IsValid());
+ ValueType* v = &root;
+ bool exist = true;
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
+ v->PushBack(ValueType().Move(), allocator);
+ v = &((*v)[v->Size() - 1]);
+ exist = false;
+ }
+ else {
+ if (t->index == kPointerInvalidIndex) { // must be object name
+ if (!v->IsObject())
+ v->SetObject(); // Change to Object
+ }
+ else { // object name or array index
+ if (!v->IsArray() && !v->IsObject())
+ v->SetArray(); // Change to Array
+ }
+
+ if (v->IsArray()) {
+ if (t->index >= v->Size()) {
+ v->Reserve(t->index + 1, allocator);
+ while (t->index >= v->Size())
+ v->PushBack(ValueType().Move(), allocator);
+ exist = false;
+ }
+ v = &((*v)[t->index]);
+ }
+ else {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd()) {
+ v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
+ v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
+ exist = false;
+ }
+ else
+ v = &m->value;
+ }
+ }
+ }
+
+ if (alreadyExist)
+ *alreadyExist = exist;
+
+ return *v;
+ }
+
+ //! Creates a value in a document.
+ /*!
+ \param document A document to be resolved.
+ \param alreadyExist If non-null, it stores whether the resolved value is already exist.
+ \return The resolved newly created, or already exists value.
+ */
+ template <typename stackAllocator>
+ ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
+ return Create(document, document.GetAllocator(), alreadyExist);
+ }
+
+ //@}
+
+ //!@name Query value
+ //@{
+
+ //! Query a value in a subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
+ \return Pointer to the value if it can be resolved. Otherwise null.
+
+ \note
+ There are only 3 situations when a value cannot be resolved:
+ 1. A value in the path is not an array nor object.
+ 2. An object value does not contain the token.
+ 3. A token is out of range of an array value.
+
+ Use unresolvedTokenIndex to retrieve the token index.
+ */
+ ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
+ RAPIDJSON_ASSERT(IsValid());
+ ValueType* v = &root;
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ switch (v->GetType()) {
+ case kObjectType:
+ {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd())
+ break;
+ v = &m->value;
+ }
+ continue;
+ case kArrayType:
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
+ break;
+ v = &((*v)[t->index]);
+ continue;
+ default:
+ break;
+ }
+
+ // Error: unresolved token
+ if (unresolvedTokenIndex)
+ *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
+ return 0;
+ }
+ return v;
+ }
+
+ //! Query a const value in a const subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \return Pointer to the value if it can be resolved. Otherwise null.
+ */
+ const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
+ return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
+ }
+
+ //@}
+
+ //!@name Query a value with default
+ //@{
+
+ //! Query a value in a subtree with default value.
+ /*!
+ Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
+ So that this function always succeed.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param defaultValue Default value to be cloned if the value was not exists.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
+ }
+
+ //! Query a value in a subtree with default null-terminated string.
+ ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.SetString(defaultValue, allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Query a value in a subtree with default std::basic_string.
+ ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.SetString(defaultValue, allocator);
+ }
+#endif
+
+ //! Query a value in a subtree with default primitive value.
+ /*!
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
+ return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
+ }
+
+ //! Query a value in a document with default value.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+ //! Query a value in a document with default null-terminated string.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Query a value in a document with default std::basic_string.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+#endif
+
+ //! Query a value in a document with default primitive value.
+ /*!
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T, typename stackAllocator>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+ //@}
+
+ //!@name Set a value
+ //@{
+
+ //! Set a value in a subtree, with move semantics.
+ /*!
+ It creates all parents if they are not exist or types are different to the tokens.
+ So this function always succeeds but potentially remove existing values.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param value Value to be set.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = value;
+ }
+
+ //! Set a value in a subtree, with copy semantics.
+ ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator).CopyFrom(value, allocator);
+ }
+
+ //! Set a null-terminated string in a subtree.
+ ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value, allocator).Move();
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Set a std::basic_string in a subtree.
+ ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value, allocator).Move();
+ }
+#endif
+
+ //! Set a primitive value in a subtree.
+ /*!
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value).Move();
+ }
+
+ //! Set a value in a document, with move semantics.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
+ return Create(document) = value;
+ }
+
+ //! Set a value in a document, with copy semantics.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
+ return Create(document).CopyFrom(value, document.GetAllocator());
+ }
+
+ //! Set a null-terminated string in a document.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
+ return Create(document) = ValueType(value, document.GetAllocator()).Move();
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Sets a std::basic_string in a document.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
+ return Create(document) = ValueType(value, document.GetAllocator()).Move();
+ }
+#endif
+
+ //! Set a primitive value in a document.
+ /*!
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T, typename stackAllocator>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
+ return Create(document) = value;
+ }
+
+ //@}
+
+ //!@name Swap a value
+ //@{
+
+ //! Swap a value with a value in a subtree.
+ /*!
+ It creates all parents if they are not exist or types are different to the tokens.
+ So this function always succeeds but potentially remove existing values.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param value Value to be swapped.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator).Swap(value);
+ }
+
+ //! Swap a value with a value in a document.
+ template <typename stackAllocator>
+ ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
+ return Create(document).Swap(value);
+ }
+
+ //@}
+
+ //! Erase a value in a subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \return Whether the resolved value is found and erased.
+
+ \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
+ */
+ bool Erase(ValueType& root) const {
+ RAPIDJSON_ASSERT(IsValid());
+ if (tokenCount_ == 0) // Cannot erase the root
+ return false;
+
+ ValueType* v = &root;
+ const Token* last = tokens_ + (tokenCount_ - 1);
+ for (const Token *t = tokens_; t != last; ++t) {
+ switch (v->GetType()) {
+ case kObjectType:
+ {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd())
+ return false;
+ v = &m->value;
+ }
+ break;
+ case kArrayType:
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
+ return false;
+ v = &((*v)[t->index]);
+ break;
+ default:
+ return false;
+ }
+ }
+
+ switch (v->GetType()) {
+ case kObjectType:
+ return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
+ case kArrayType:
+ if (last->index == kPointerInvalidIndex || last->index >= v->Size())
+ return false;
+ v->Erase(v->Begin() + last->index);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+private:
+ //! Clone the content from rhs to this.
+ /*!
+ \param rhs Source pointer.
+ \param extraToken Extra tokens to be allocated.
+ \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
+ \return Start of non-occupied name buffer, for storing extra names.
+ */
+ Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
+ if (!allocator_) // allocator is independently owned.
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+
+ size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
+ for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
+ nameBufferSize += t->length;
+
+ tokenCount_ = rhs.tokenCount_ + extraToken;
+ tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
+ nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
+ if (rhs.tokenCount_ > 0) {
+ std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
+ }
+ if (nameBufferSize > 0) {
+ std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
+ }
+
+ // Adjust pointers to name buffer
+ std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
+ for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
+ t->name += diff;
+
+ return nameBuffer_ + nameBufferSize;
+ }
+
+ //! Check whether a character should be percent-encoded.
+ /*!
+ According to RFC 3986 2.3 Unreserved Characters.
+ \param c The character (code unit) to be tested.
+ */
+ bool NeedPercentEncode(Ch c) const {
+ return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
+ }
+
+ //! Parse a JSON String or its URI fragment representation into tokens.
+#ifndef __clang__ // -Wdocumentation
+ /*!
+ \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
+ \param length Length of the source string.
+ \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
+ */
+#endif
+ void Parse(const Ch* source, size_t length) {
+ RAPIDJSON_ASSERT(source != NULL);
+ RAPIDJSON_ASSERT(nameBuffer_ == 0);
+ RAPIDJSON_ASSERT(tokens_ == 0);
+
+ // Create own allocator if user did not supply.
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+
+ // Count number of '/' as tokenCount
+ tokenCount_ = 0;
+ for (const Ch* s = source; s != source + length; s++)
+ if (*s == '/')
+ tokenCount_++;
+
+ Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
+ Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
+ size_t i = 0;
+
+ // Detect if it is a URI fragment
+ bool uriFragment = false;
+ if (source[i] == '#') {
+ uriFragment = true;
+ i++;
+ }
+
+ if (i != length && source[i] != '/') {
+ parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
+ goto error;
+ }
+
+ while (i < length) {
+ RAPIDJSON_ASSERT(source[i] == '/');
+ i++; // consumes '/'
+
+ token->name = name;
+ bool isNumber = true;
+
+ while (i < length && source[i] != '/') {
+ Ch c = source[i];
+ if (uriFragment) {
+ // Decoding percent-encoding for URI fragment
+ if (c == '%') {
+ PercentDecodeStream is(&source[i], source + length);
+ GenericInsituStringStream<EncodingType> os(name);
+ Ch* begin = os.PutBegin();
+ if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
+ parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
+ goto error;
+ }
+ size_t len = os.PutEnd(begin);
+ i += is.Tell() - 1;
+ if (len == 1)
+ c = *name;
+ else {
+ name += len;
+ isNumber = false;
+ i++;
+ continue;
+ }
+ }
+ else if (NeedPercentEncode(c)) {
+ parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
+ goto error;
+ }
+ }
+
+ i++;
+
+ // Escaping "~0" -> '~', "~1" -> '/'
+ if (c == '~') {
+ if (i < length) {
+ c = source[i];
+ if (c == '0') c = '~';
+ else if (c == '1') c = '/';
+ else {
+ parseErrorCode_ = kPointerParseErrorInvalidEscape;
+ goto error;
+ }
+ i++;
+ }
+ else {
+ parseErrorCode_ = kPointerParseErrorInvalidEscape;
+ goto error;
+ }
+ }
+
+ // First check for index: all of characters are digit
+ if (c < '0' || c > '9')
+ isNumber = false;
+
+ *name++ = c;
+ }
+ token->length = static_cast<SizeType>(name - token->name);
+ if (token->length == 0)
+ isNumber = false;
+ *name++ = '\0'; // Null terminator
+
+ // Second check for index: more than one digit cannot have leading zero
+ if (isNumber && token->length > 1 && token->name[0] == '0')
+ isNumber = false;
+
+ // String to SizeType conversion
+ SizeType n = 0;
+ if (isNumber) {
+ for (size_t j = 0; j < token->length; j++) {
+ SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
+ if (m < n) { // overflow detection
+ isNumber = false;
+ break;
+ }
+ n = m;
+ }
+ }
+
+ token->index = isNumber ? n : kPointerInvalidIndex;
+ token++;
+ }
+
+ RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
+ parseErrorCode_ = kPointerParseErrorNone;
+ return;
+
+ error:
+ Allocator::Free(tokens_);
+ nameBuffer_ = 0;
+ tokens_ = 0;
+ tokenCount_ = 0;
+ parseErrorOffset_ = i;
+ return;
+ }
+
+ //! Stringify to string or URI fragment representation.
+ /*!
+ \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
+ \tparam OutputStream type of output stream.
+ \param os The output stream.
+ */
+ template<bool uriFragment, typename OutputStream>
+ bool Stringify(OutputStream& os) const {
+ RAPIDJSON_ASSERT(IsValid());
+
+ if (uriFragment)
+ os.Put('#');
+
+ for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ os.Put('/');
+ for (size_t j = 0; j < t->length; j++) {
+ Ch c = t->name[j];
+ if (c == '~') {
+ os.Put('~');
+ os.Put('0');
+ }
+ else if (c == '/') {
+ os.Put('~');
+ os.Put('1');
+ }
+ else if (uriFragment && NeedPercentEncode(c)) {
+ // Transcode to UTF8 sequence
+ GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
+ PercentEncodeStream<OutputStream> target(os);
+ if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
+ return false;
+ j += source.Tell() - 1;
+ }
+ else
+ os.Put(c);
+ }
+ }
+ return true;
+ }
+
+ //! A helper stream for decoding a percent-encoded sequence into code unit.
+ /*!
+ This stream decodes %XY triplet into code unit (0-255).
+ If it encounters invalid characters, it sets output code unit as 0 and
+ mark invalid, and to be checked by IsValid().
+ */
+ class PercentDecodeStream {
+ public:
+ typedef typename ValueType::Ch Ch;
+
+ //! Constructor
+ /*!
+ \param source Start of the stream
+ \param end Past-the-end of the stream.
+ */
+ PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
+
+ Ch Take() {
+ if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
+ valid_ = false;
+ return 0;
+ }
+ src_++;
+ Ch c = 0;
+ for (int j = 0; j < 2; j++) {
+ c = static_cast<Ch>(c << 4);
+ Ch h = *src_;
+ if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
+ else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
+ else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
+ else {
+ valid_ = false;
+ return 0;
+ }
+ src_++;
+ }
+ return c;
+ }
+
+ size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+ bool IsValid() const { return valid_; }
+
+ private:
+ const Ch* src_; //!< Current read position.
+ const Ch* head_; //!< Original head of the string.
+ const Ch* end_; //!< Past-the-end position.
+ bool valid_; //!< Whether the parsing is valid.
+ };
+
+ //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
+ template <typename OutputStream>
+ class PercentEncodeStream {
+ public:
+ PercentEncodeStream(OutputStream& os) : os_(os) {}
+ void Put(char c) { // UTF-8 must be byte
+ unsigned char u = static_cast<unsigned char>(c);
+ static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ os_.Put('%');
+ os_.Put(hexDigits[u >> 4]);
+ os_.Put(hexDigits[u & 15]);
+ }
+ private:
+ OutputStream& os_;
+ };
+
+ Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
+ Allocator* ownAllocator_; //!< Allocator owned by this Pointer.
+ Ch* nameBuffer_; //!< A buffer containing all names in tokens.
+ Token* tokens_; //!< A list of tokens.
+ size_t tokenCount_; //!< Number of tokens in tokens_.
+ size_t parseErrorOffset_; //!< Offset in code unit when parsing fail.
+ PointerParseErrorCode parseErrorCode_; //!< Parsing error code.
+};
+
+//! GenericPointer for Value (UTF-8, default allocator).
+typedef GenericPointer<Value> Pointer;
+
+//!@name Helper functions for GenericPointer
+//@{
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
+ return pointer.Create(root, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
+ return pointer.Create(document);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
+ return pointer.Get(root, unresolvedTokenIndex);
+}
+
+template <typename T>
+const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
+ return pointer.Get(root, unresolvedTokenIndex);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
+}
+
+template <typename T, typename CharType, size_t N>
+const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+#endif
+
+template <typename T, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+#endif
+
+template <typename T, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+#endif
+
+template <typename DocumentType, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+#endif
+
+template <typename DocumentType, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+#endif
+
+template <typename T, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+#endif
+
+template <typename T, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
+ return pointer.Set(document, value);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
+ return pointer.Set(document, value);
+}
+#endif
+
+template <typename DocumentType, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+#endif
+
+template <typename DocumentType, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Swap(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
+ return pointer.Swap(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
+ return pointer.Erase(root);
+}
+
+template <typename T, typename CharType, size_t N>
+bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
+}
+
+//@}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_POINTER_H_
diff --git a/include/rapidjson/prettywriter.h b/include/rapidjson/prettywriter.h
new file mode 100644
index 00000000..0dcb0fee
--- /dev/null
+++ b/include/rapidjson/prettywriter.h
@@ -0,0 +1,255 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_PRETTYWRITER_H_
+#define RAPIDJSON_PRETTYWRITER_H_
+
+#include "writer.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Combination of PrettyWriter format flags.
+/*! \see PrettyWriter::SetFormatOptions
+ */
+enum PrettyFormatOptions {
+ kFormatDefault = 0, //!< Default pretty formatting.
+ kFormatSingleLineArray = 1 //!< Format arrays on a single line.
+};
+
+//! Writer with indentation and spacing.
+/*!
+ \tparam OutputStream Type of ouptut os.
+ \tparam SourceEncoding Encoding of source string.
+ \tparam TargetEncoding Encoding of output stream.
+ \tparam StackAllocator Type of allocator for allocating memory of stack.
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
+class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
+public:
+ typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
+ typedef typename Base::Ch Ch;
+
+ //! Constructor
+ /*! \param os Output stream.
+ \param allocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of stack.
+ */
+ explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
+
+
+ explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+
+ //! Set custom indentation.
+ /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
+ \param indentCharCount Number of indent characters for each indentation level.
+ \note The default indentation is 4 spaces.
+ */
+ PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
+ RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
+ indentChar_ = indentChar;
+ indentCharCount_ = indentCharCount;
+ return *this;
+ }
+
+ //! Set pretty writer formatting options.
+ /*! \param options Formatting options.
+ */
+ PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
+ formatOptions_ = options;
+ return *this;
+ }
+
+ /*! @name Implementation of Handler
+ \see Handler
+ */
+ //@{
+
+ bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
+ bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
+ bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
+ bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
+ bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
+ bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
+ bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
+
+ bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ PrettyPrefix(kNumberType);
+ return Base::WriteString(str, length);
+ }
+
+ bool String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ PrettyPrefix(kStringType);
+ return Base::WriteString(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool String(const std::basic_string<Ch>& str) {
+ return String(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool StartObject() {
+ PrettyPrefix(kObjectType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
+ return Base::WriteStartObject();
+ }
+
+ bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool Key(const std::basic_string<Ch>& str) {
+ return Key(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+ RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
+ bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+ if (!empty) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ bool ret = Base::WriteEndObject();
+ (void)ret;
+ RAPIDJSON_ASSERT(ret == true);
+ if (Base::level_stack_.Empty()) // end of json text
+ Base::os_->Flush();
+ return true;
+ }
+
+ bool StartArray() {
+ PrettyPrefix(kArrayType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
+ return Base::WriteStartArray();
+ }
+
+ bool EndArray(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+ RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
+ bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+ if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ bool ret = Base::WriteEndArray();
+ (void)ret;
+ RAPIDJSON_ASSERT(ret == true);
+ if (Base::level_stack_.Empty()) // end of json text
+ Base::os_->Flush();
+ return true;
+ }
+
+ //@}
+
+ /*! @name Convenience extensions */
+ //@{
+
+ //! Simpler but slower overload.
+ bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+ bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+ //@}
+
+ //! Write a raw JSON value.
+ /*!
+ For user to write a stringified JSON as a value.
+
+ \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
+ \param length Length of the json.
+ \param type Type of the root of json.
+ \note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
+ */
+ bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
+
+protected:
+ void PrettyPrefix(Type type) {
+ (void)type;
+ if (Base::level_stack_.GetSize() != 0) { // this value is not at root
+ typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
+
+ if (level->inArray) {
+ if (level->valueCount > 0) {
+ Base::os_->Put(','); // add comma if it is not the first element in array
+ if (formatOptions_ & kFormatSingleLineArray)
+ Base::os_->Put(' ');
+ }
+
+ if (!(formatOptions_ & kFormatSingleLineArray)) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ }
+ else { // in object
+ if (level->valueCount > 0) {
+ if (level->valueCount % 2 == 0) {
+ Base::os_->Put(',');
+ Base::os_->Put('\n');
+ }
+ else {
+ Base::os_->Put(':');
+ Base::os_->Put(' ');
+ }
+ }
+ else
+ Base::os_->Put('\n');
+
+ if (level->valueCount % 2 == 0)
+ WriteIndent();
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else {
+ RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
+ Base::hasRoot_ = true;
+ }
+ }
+
+ void WriteIndent() {
+ size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
+ PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
+ }
+
+ Ch indentChar_;
+ unsigned indentCharCount_;
+ PrettyFormatOptions formatOptions_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ PrettyWriter(const PrettyWriter&);
+ PrettyWriter& operator=(const PrettyWriter&);
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h
new file mode 100644
index 00000000..053b2ce4
--- /dev/null
+++ b/include/rapidjson/rapidjson.h
@@ -0,0 +1,615 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#define RAPIDJSON_RAPIDJSON_H_
+
+/*!\file rapidjson.h
+ \brief common definitions and configuration
+
+ \see RAPIDJSON_CONFIG
+ */
+
+/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration
+ \brief Configuration macros for library features
+
+ Some RapidJSON features are configurable to adapt the library to a wide
+ variety of platforms, environments and usage scenarios. Most of the
+ features can be configured in terms of overriden or predefined
+ preprocessor macros at compile-time.
+
+ Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
+
+ \note These macros should be given on the compiler command-line
+ (where applicable) to avoid inconsistent values when compiling
+ different translation units of a single application.
+ */
+
+#include <cstdlib> // malloc(), realloc(), free(), size_t
+#include <cstring> // memset(), memcpy(), memmove(), memcmp()
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_VERSION_STRING
+//
+// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
+//
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+// token stringification
+#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
+#define RAPIDJSON_DO_STRINGIFY(x) #x
+//!@endcond
+
+/*! \def RAPIDJSON_MAJOR_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Major version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_MINOR_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Minor version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_PATCH_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Patch version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_VERSION_STRING
+ \ingroup RAPIDJSON_CONFIG
+ \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
+*/
+#define RAPIDJSON_MAJOR_VERSION 1
+#define RAPIDJSON_MINOR_VERSION 1
+#define RAPIDJSON_PATCH_VERSION 0
+#define RAPIDJSON_VERSION_STRING \
+ RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NAMESPACE_(BEGIN|END)
+/*! \def RAPIDJSON_NAMESPACE
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace
+
+ In order to avoid symbol clashes and/or "One Definition Rule" errors
+ between multiple inclusions of (different versions of) RapidJSON in
+ a single binary, users can customize the name of the main RapidJSON
+ namespace.
+
+ In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
+ to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple
+ levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
+ RAPIDJSON_NAMESPACE_END need to be defined as well:
+
+ \code
+ // in some .cpp file
+ #define RAPIDJSON_NAMESPACE my::rapidjson
+ #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
+ #define RAPIDJSON_NAMESPACE_END } }
+ #include "rapidjson/..."
+ \endcode
+
+ \see rapidjson
+ */
+/*! \def RAPIDJSON_NAMESPACE_BEGIN
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace (opening expression)
+ \see RAPIDJSON_NAMESPACE
+*/
+/*! \def RAPIDJSON_NAMESPACE_END
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace (closing expression)
+ \see RAPIDJSON_NAMESPACE
+*/
+#ifndef RAPIDJSON_NAMESPACE
+#define RAPIDJSON_NAMESPACE rapidjson
+#endif
+#ifndef RAPIDJSON_NAMESPACE_BEGIN
+#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
+#endif
+#ifndef RAPIDJSON_NAMESPACE_END
+#define RAPIDJSON_NAMESPACE_END }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_HAS_STDSTRING
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
+#else
+#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
+#endif
+/*! \def RAPIDJSON_HAS_STDSTRING
+ \ingroup RAPIDJSON_CONFIG
+ \brief Enable RapidJSON support for \c std::string
+
+ By defining this preprocessor symbol to \c 1, several convenience functions for using
+ \ref rapidjson::GenericValue with \c std::string are enabled, especially
+ for construction and comparison.
+
+ \hideinitializer
+*/
+#endif // !defined(RAPIDJSON_HAS_STDSTRING)
+
+#if RAPIDJSON_HAS_STDSTRING
+#include <string>
+#endif // RAPIDJSON_HAS_STDSTRING
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_INT64DEFINE
+
+/*! \def RAPIDJSON_NO_INT64DEFINE
+ \ingroup RAPIDJSON_CONFIG
+ \brief Use external 64-bit integer types.
+
+ RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types
+ to be available at global scope.
+
+ If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to
+ prevent RapidJSON from defining its own types.
+*/
+#ifndef RAPIDJSON_NO_INT64DEFINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
+#include "msinttypes/stdint.h"
+#include "msinttypes/inttypes.h"
+#else
+// Other compilers should have this.
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+//!@endcond
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_INT64DEFINE
+#endif
+#endif // RAPIDJSON_NO_INT64TYPEDEF
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_FORCEINLINE
+
+#ifndef RAPIDJSON_FORCEINLINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#if defined(_MSC_VER) && defined(NDEBUG)
+#define RAPIDJSON_FORCEINLINE __forceinline
+#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG)
+#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
+#else
+#define RAPIDJSON_FORCEINLINE
+#endif
+//!@endcond
+#endif // RAPIDJSON_FORCEINLINE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ENDIAN
+#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
+#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
+
+//! Endianness of the machine.
+/*!
+ \def RAPIDJSON_ENDIAN
+ \ingroup RAPIDJSON_CONFIG
+
+ GCC 4.6 provided macro for detecting endianness of the target machine. But other
+ compilers may not have this. User can define RAPIDJSON_ENDIAN to either
+ \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN.
+
+ Default detection implemented with reference to
+ \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html
+ \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp
+*/
+#ifndef RAPIDJSON_ENDIAN
+// Detect with GCC 4.6's macro
+# ifdef __BYTE_ORDER__
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif // __BYTE_ORDER__
+// Detect with GLIBC's endian.h
+# elif defined(__GLIBC__)
+# include <endian.h>
+# if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif (__BYTE_ORDER == __BIG_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif // __GLIBC__
+// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
+# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+// Detect with architecture macros
+# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(_MSC_VER) && defined(_M_ARM)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
+# define RAPIDJSON_ENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif
+#endif // RAPIDJSON_ENDIAN
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_64BIT
+
+//! Whether using 64-bit architecture
+#ifndef RAPIDJSON_64BIT
+#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__)
+#define RAPIDJSON_64BIT 1
+#else
+#define RAPIDJSON_64BIT 0
+#endif
+#endif // RAPIDJSON_64BIT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ALIGN
+
+//! Data alignment of the machine.
+/*! \ingroup RAPIDJSON_CONFIG
+ \param x pointer to align
+
+ Some machines require strict data alignment. Currently the default uses 4 bytes
+ alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
+ User can customize by defining the RAPIDJSON_ALIGN function macro.
+*/
+#ifndef RAPIDJSON_ALIGN
+#if RAPIDJSON_64BIT == 1
+#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
+#else
+#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_UINT64_C2
+
+//! Construct a 64-bit literal by a pair of 32-bit integer.
+/*!
+ 64-bit literal with or without ULL suffix is prone to compiler warnings.
+ UINT64_C() is C macro which cause compilation problems.
+ Use this macro to define 64-bit constants by a pair of 32-bit integer.
+*/
+#ifndef RAPIDJSON_UINT64_C2
+#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+//! Use only lower 48-bit address for some pointers.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+
+ This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.
+ The higher 16-bit can be used for storing other data.
+ \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.
+*/
+#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION
+#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
+#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
+#else
+#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
+#endif
+#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
+#if RAPIDJSON_64BIT != 1
+#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
+#endif
+#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
+#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
+#else
+#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
+#define RAPIDJSON_GETPOINTER(type, p) (p)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
+
+/*! \def RAPIDJSON_SIMD
+ \ingroup RAPIDJSON_CONFIG
+ \brief Enable SSE2/SSE4.2 optimization.
+
+ RapidJSON supports optimized implementations for some parsing operations
+ based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
+ processors.
+
+ To enable these optimizations, two different symbols can be defined;
+ \code
+ // Enable SSE2 optimization.
+ #define RAPIDJSON_SSE2
+
+ // Enable SSE4.2 optimization.
+ #define RAPIDJSON_SSE42
+ \endcode
+
+ \c RAPIDJSON_SSE42 takes precedence, if both are defined.
+
+ If any of these symbols is defined, RapidJSON defines the macro
+ \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
+*/
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
+ || defined(RAPIDJSON_DOXYGEN_RUNNING)
+#define RAPIDJSON_SIMD
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_SIZETYPEDEFINE
+
+#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
+/*! \def RAPIDJSON_NO_SIZETYPEDEFINE
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-provided \c SizeType definition.
+
+ In order to avoid using 32-bit size types for indexing strings and arrays,
+ define this preprocessor symbol and provide the type rapidjson::SizeType
+ before including RapidJSON:
+ \code
+ #define RAPIDJSON_NO_SIZETYPEDEFINE
+ namespace rapidjson { typedef ::std::size_t SizeType; }
+ #include "rapidjson/..."
+ \endcode
+
+ \see rapidjson::SizeType
+*/
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_SIZETYPEDEFINE
+#endif
+RAPIDJSON_NAMESPACE_BEGIN
+//! Size type (for string lengths, array sizes, etc.)
+/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
+ instead of using \c size_t. Users may override the SizeType by defining
+ \ref RAPIDJSON_NO_SIZETYPEDEFINE.
+*/
+typedef unsigned SizeType;
+RAPIDJSON_NAMESPACE_END
+#endif
+
+// always import std::size_t to rapidjson namespace
+RAPIDJSON_NAMESPACE_BEGIN
+using std::size_t;
+RAPIDJSON_NAMESPACE_END
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ASSERT
+
+//! Assertion.
+/*! \ingroup RAPIDJSON_CONFIG
+ By default, rapidjson uses C \c assert() for internal assertions.
+ User can override it by defining RAPIDJSON_ASSERT(x) macro.
+
+ \note Parsing errors are handled and can be customized by the
+ \ref RAPIDJSON_ERRORS APIs.
+*/
+#ifndef RAPIDJSON_ASSERT
+#include <cassert>
+#define RAPIDJSON_ASSERT(x) assert(x)
+#endif // RAPIDJSON_ASSERT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_STATIC_ASSERT
+
+// Adopt from boost
+#ifndef RAPIDJSON_STATIC_ASSERT
+#ifndef __clang__
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#endif
+RAPIDJSON_NAMESPACE_BEGIN
+template <bool x> struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
+template<int x> struct StaticAssertTest {};
+RAPIDJSON_NAMESPACE_END
+
+#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
+#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
+#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
+
+#if defined(__GNUC__)
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
+#else
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+#ifndef __clang__
+//!@endcond
+#endif
+
+/*! \def RAPIDJSON_STATIC_ASSERT
+ \brief (Internal) macro to check for conditions at compile-time
+ \param x compile-time condition
+ \hideinitializer
+ */
+#define RAPIDJSON_STATIC_ASSERT(x) \
+ typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
+ sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
+ RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
+
+//! Compiler branching hint for expression with high probability to be true.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+ \param x Boolean expression likely to be true.
+*/
+#ifndef RAPIDJSON_LIKELY
+#if defined(__GNUC__) || defined(__clang__)
+#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
+#else
+#define RAPIDJSON_LIKELY(x) (x)
+#endif
+#endif
+
+//! Compiler branching hint for expression with low probability to be true.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+ \param x Boolean expression unlikely to be true.
+*/
+#ifndef RAPIDJSON_UNLIKELY
+#if defined(__GNUC__) || defined(__clang__)
+#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define RAPIDJSON_UNLIKELY(x) (x)
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+
+#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
+#define RAPIDJSON_MULTILINEMACRO_END \
+} while((void)0, 0)
+
+// adopted from Boost
+#define RAPIDJSON_VERSION_CODE(x,y,z) \
+ (((x)*100000) + ((y)*100) + (z))
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
+
+#if defined(__GNUC__)
+#define RAPIDJSON_GNUC \
+ RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
+#endif
+
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
+
+#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
+#define RAPIDJSON_DIAG_OFF(x) \
+ RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
+
+// push/pop support in Clang and GCC>=4.6
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
+#else // GCC >= 4.2, < 4.6
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+#endif
+
+#elif defined(_MSC_VER)
+
+// pragma (MSVC specific)
+#define RAPIDJSON_PRAGMA(x) __pragma(x)
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
+
+#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
+
+#else
+
+#define RAPIDJSON_DIAG_OFF(x) /* ignored */
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+
+#endif // RAPIDJSON_DIAG_*
+
+///////////////////////////////////////////////////////////////////////////////
+// C++11 features
+
+#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#if defined(__clang__)
+#if __has_feature(cxx_rvalue_references) && \
+ (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1600)
+
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
+// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
+#else
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
+#endif
+#endif
+#if RAPIDJSON_HAS_CXX11_NOEXCEPT
+#define RAPIDJSON_NOEXCEPT noexcept
+#else
+#define RAPIDJSON_NOEXCEPT /* noexcept */
+#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
+
+// no automatic detection, yet
+#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
+#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
+#endif
+
+#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1700)
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
+#else
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
+
+//!@endcond
+
+///////////////////////////////////////////////////////////////////////////////
+// new/delete
+
+#ifndef RAPIDJSON_NEW
+///! customization point for global \c new
+#define RAPIDJSON_NEW(x) new x
+#endif
+#ifndef RAPIDJSON_DELETE
+///! customization point for global \c delete
+#define RAPIDJSON_DELETE(x) delete x
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Type
+
+/*! \namespace rapidjson
+ \brief main RapidJSON namespace
+ \see RAPIDJSON_NAMESPACE
+*/
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Type of JSON value
+enum Type {
+ kNullType = 0, //!< null
+ kFalseType = 1, //!< false
+ kTrueType = 2, //!< true
+ kObjectType = 3, //!< object
+ kArrayType = 4, //!< array
+ kStringType = 5, //!< string
+ kNumberType = 6 //!< number
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h
new file mode 100644
index 00000000..19f8849b
--- /dev/null
+++ b/include/rapidjson/reader.h
@@ -0,0 +1,1879 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_READER_H_
+#define RAPIDJSON_READER_H_
+
+/*! \file reader.h */
+
+#include "allocators.h"
+#include "stream.h"
+#include "encodedstream.h"
+#include "internal/meta.h"
+#include "internal/stack.h"
+#include "internal/strtod.h"
+#include <limits>
+
+#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+#endif
+#ifdef RAPIDJSON_SSE42
+#include <nmmintrin.h>
+#elif defined(RAPIDJSON_SSE2)
+#include <emmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+RAPIDJSON_DIAG_OFF(4702) // unreachable code
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(old-style-cast)
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define RAPIDJSON_NOTHING /* deliberately empty */
+#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
+//!@endcond
+
+/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
+ \ingroup RAPIDJSON_ERRORS
+ \brief Macro to indicate a parse error.
+ \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+ \param offset position of the error in JSON input (\c size_t)
+
+ This macros can be used as a customization point for the internal
+ error handling mechanism of RapidJSON.
+
+ A common usage model is to throw an exception instead of requiring the
+ caller to explicitly check the \ref rapidjson::GenericReader::Parse's
+ return value:
+
+ \code
+ #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
+ throw ParseException(parseErrorCode, #parseErrorCode, offset)
+
+ #include <stdexcept> // std::runtime_error
+ #include "rapidjson/error/error.h" // rapidjson::ParseResult
+
+ struct ParseException : std::runtime_error, rapidjson::ParseResult {
+ ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
+ : std::runtime_error(msg), ParseResult(code, offset) {}
+ };
+
+ #include "rapidjson/reader.h"
+ \endcode
+
+ \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
+ */
+#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
+#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
+ SetParseError(parseErrorCode, offset); \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+/*! \def RAPIDJSON_PARSE_ERROR
+ \ingroup RAPIDJSON_ERRORS
+ \brief (Internal) macro to indicate and handle a parse error.
+ \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+ \param offset position of the error in JSON input (\c size_t)
+
+ Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
+
+ \see RAPIDJSON_PARSE_ERROR_NORETURN
+ \hideinitializer
+ */
+#ifndef RAPIDJSON_PARSE_ERROR
+#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+#include "error/error.h" // ParseErrorCode, ParseResult
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseFlag
+
+/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-defined kParseDefaultFlags definition.
+
+ User can define this as any \c ParseFlag combinations.
+*/
+#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
+#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
+#endif
+
+//! Combination of parseFlags
+/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
+ */
+enum ParseFlag {
+ kParseNoFlags = 0, //!< No flags are set.
+ kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
+ kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
+ kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
+ kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
+ kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
+ kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
+ kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
+ kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
+ kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
+ kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Handler
+
+/*! \class rapidjson::Handler
+ \brief Concept for receiving events from GenericReader upon parsing.
+ The functions return true if no error occurs. If they return false,
+ the event publisher should terminate the process.
+\code
+concept Handler {
+ typename Ch;
+
+ bool Null();
+ bool Bool(bool b);
+ bool Int(int i);
+ bool Uint(unsigned i);
+ bool Int64(int64_t i);
+ bool Uint64(uint64_t i);
+ bool Double(double d);
+ /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
+ bool RawNumber(const Ch* str, SizeType length, bool copy);
+ bool String(const Ch* str, SizeType length, bool copy);
+ bool StartObject();
+ bool Key(const Ch* str, SizeType length, bool copy);
+ bool EndObject(SizeType memberCount);
+ bool StartArray();
+ bool EndArray(SizeType elementCount);
+};
+\endcode
+*/
+///////////////////////////////////////////////////////////////////////////////
+// BaseReaderHandler
+
+//! Default implementation of Handler.
+/*! This can be used as base class of any reader handler.
+ \note implements Handler concept
+*/
+template<typename Encoding = UTF8<>, typename Derived = void>
+struct BaseReaderHandler {
+ typedef typename Encoding::Ch Ch;
+
+ typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
+
+ bool Default() { return true; }
+ bool Null() { return static_cast<Override&>(*this).Default(); }
+ bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
+ bool Int(int) { return static_cast<Override&>(*this).Default(); }
+ bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
+ bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
+ bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
+ bool Double(double) { return static_cast<Override&>(*this).Default(); }
+ /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
+ bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
+ bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
+ bool StartObject() { return static_cast<Override&>(*this).Default(); }
+ bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
+ bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
+ bool StartArray() { return static_cast<Override&>(*this).Default(); }
+ bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamLocalCopy
+
+namespace internal {
+
+template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
+class StreamLocalCopy;
+
+//! Do copy optimization.
+template<typename Stream>
+class StreamLocalCopy<Stream, 1> {
+public:
+ StreamLocalCopy(Stream& original) : s(original), original_(original) {}
+ ~StreamLocalCopy() { original_ = s; }
+
+ Stream s;
+
+private:
+ StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+
+ Stream& original_;
+};
+
+//! Keep reference.
+template<typename Stream>
+class StreamLocalCopy<Stream, 0> {
+public:
+ StreamLocalCopy(Stream& original) : s(original) {}
+
+ Stream& s;
+
+private:
+ StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// SkipWhitespace
+
+//! Skip the JSON white spaces in a stream.
+/*! \param is A input stream for skipping white spaces.
+ \note This function has SSE2/SSE4.2 specialization.
+*/
+template<typename InputStream>
+void SkipWhitespace(InputStream& is) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ InputStream& s(copy.s);
+
+ typename InputStream::Ch c;
+ while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
+ s.Take();
+}
+
+inline const char* SkipWhitespace(const char* p, const char* end) {
+ while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ return p;
+}
+
+#ifdef RAPIDJSON_SSE42
+//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ // Fast return for single non-whitespace
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // 16-byte align to the next boundary
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // The rest of string using SIMD
+ static const char whitespace[16] = " \n\r\t";
+ const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
+ if (r != 0) { // some of characters is non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+}
+
+inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
+ // Fast return for single non-whitespace
+ if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ else
+ return p;
+
+ // The middle of string using SIMD
+ static const char whitespace[16] = " \n\r\t";
+ const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
+
+ for (; p <= end - 16; p += 16) {
+ const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
+ const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
+ if (r != 0) { // some of characters is non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+
+ return SkipWhitespace(p, end);
+}
+
+#elif defined(RAPIDJSON_SSE2)
+
+//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ // Fast return for single non-whitespace
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // 16-byte align to the next boundary
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // The rest of string
+ #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
+ static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
+ #undef C16
+
+ const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
+ const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
+ const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
+ const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ __m128i x = _mm_cmpeq_epi8(s, w0);
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
+ unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
+ if (r != 0) { // some of characters may be non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+}
+
+inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
+ // Fast return for single non-whitespace
+ if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ else
+ return p;
+
+ // The rest of string
+ #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
+ static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
+ #undef C16
+
+ const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
+ const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
+ const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
+ const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
+
+ for (; p <= end - 16; p += 16) {
+ const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
+ __m128i x = _mm_cmpeq_epi8(s, w0);
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
+ unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
+ if (r != 0) { // some of characters may be non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+
+ return SkipWhitespace(p, end);
+}
+
+#endif // RAPIDJSON_SSE2
+
+#ifdef RAPIDJSON_SIMD
+//! Template function specialization for InsituStringStream
+template<> inline void SkipWhitespace(InsituStringStream& is) {
+ is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
+}
+
+//! Template function specialization for StringStream
+template<> inline void SkipWhitespace(StringStream& is) {
+ is.src_ = SkipWhitespace_SIMD(is.src_);
+}
+
+template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
+ is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
+}
+#endif // RAPIDJSON_SIMD
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericReader
+
+//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
+/*! GenericReader parses JSON text from a stream, and send events synchronously to an
+ object implementing Handler concept.
+
+ It needs to allocate a stack for storing a single decoded string during
+ non-destructive parsing.
+
+ For in-situ parsing, the decoded string is directly written to the source
+ text string, no temporary buffer is required.
+
+ A GenericReader object can be reused for parsing multiple JSON text.
+
+ \tparam SourceEncoding Encoding of the input stream.
+ \tparam TargetEncoding Encoding of the parse output.
+ \tparam StackAllocator Allocator type for stack.
+*/
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
+class GenericReader {
+public:
+ typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
+
+ //! Constructor.
+ /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
+ \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
+ */
+ GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
+
+ //! Parse JSON text.
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept.
+ \tparam Handler Type of handler, implementing Handler concept.
+ \param is Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ ParseResult Parse(InputStream& is, Handler& handler) {
+ if (parseFlags & kParseIterativeFlag)
+ return IterativeParse<parseFlags>(is, handler);
+
+ parseResult_.Clear();
+
+ ClearStackOnExit scope(*this);
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+ else {
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (!(parseFlags & kParseStopWhenDoneFlag)) {
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+ }
+ }
+
+ return parseResult_;
+ }
+
+ //! Parse JSON text (with \ref kParseDefaultFlags)
+ /*! \tparam InputStream Type of input stream, implementing Stream concept
+ \tparam Handler Type of handler, implementing Handler concept.
+ \param is Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <typename InputStream, typename Handler>
+ ParseResult Parse(InputStream& is, Handler& handler) {
+ return Parse<kParseDefaultFlags>(is, handler);
+ }
+
+ //! Whether a parse error has occured in the last parsing.
+ bool HasParseError() const { return parseResult_.IsError(); }
+
+ //! Get the \ref ParseErrorCode of last parsing.
+ ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
+
+ //! Get the position of last parsing error in input, 0 otherwise.
+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+protected:
+ void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ GenericReader(const GenericReader&);
+ GenericReader& operator=(const GenericReader&);
+
+ void ClearStack() { stack_.Clear(); }
+
+ // clear stack on any exit from ParseStream, e.g. due to exception
+ struct ClearStackOnExit {
+ explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
+ ~ClearStackOnExit() { r_.ClearStack(); }
+ private:
+ GenericReader& r_;
+ ClearStackOnExit(const ClearStackOnExit&);
+ ClearStackOnExit& operator=(const ClearStackOnExit&);
+ };
+
+ template<unsigned parseFlags, typename InputStream>
+ void SkipWhitespaceAndComments(InputStream& is) {
+ SkipWhitespace(is);
+
+ if (parseFlags & kParseCommentsFlag) {
+ while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
+ if (Consume(is, '*')) {
+ while (true) {
+ if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
+ RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+ else if (Consume(is, '*')) {
+ if (Consume(is, '/'))
+ break;
+ }
+ else
+ is.Take();
+ }
+ }
+ else if (RAPIDJSON_LIKELY(Consume(is, '/')))
+ while (is.Peek() != '\0' && is.Take() != '\n');
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+
+ SkipWhitespace(is);
+ }
+ }
+ }
+
+ // Parse object: { string : value, ... }
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseObject(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == '{');
+ is.Take(); // Skip '{'
+
+ if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (Consume(is, '}')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+
+ for (SizeType memberCount = 0;;) {
+ if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+
+ ParseString<parseFlags>(is, handler, true);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ++memberCount;
+
+ switch (is.Peek()) {
+ case ',':
+ is.Take();
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ break;
+ case '}':
+ is.Take();
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ default:
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
+ }
+
+ if (parseFlags & kParseTrailingCommasFlag) {
+ if (is.Peek() == '}') {
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ is.Take();
+ return;
+ }
+ }
+ }
+ }
+
+ // Parse array: [ value, ... ]
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseArray(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == '[');
+ is.Take(); // Skip '['
+
+ if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (Consume(is, ']')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+
+ for (SizeType elementCount = 0;;) {
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ++elementCount;
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (Consume(is, ',')) {
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ }
+ else if (Consume(is, ']')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+
+ if (parseFlags & kParseTrailingCommasFlag) {
+ if (is.Peek() == ']') {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ is.Take();
+ return;
+ }
+ }
+ }
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseNull(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 'n');
+ is.Take();
+
+ if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Null()))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseTrue(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 't');
+ is.Take();
+
+ if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseFalse(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 'f');
+ is.Take();
+
+ if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
+ }
+
+ template<typename InputStream>
+ RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
+ if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
+ is.Take();
+ return true;
+ }
+ else
+ return false;
+ }
+
+ // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
+ template<typename InputStream>
+ unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
+ unsigned codepoint = 0;
+ for (int i = 0; i < 4; i++) {
+ Ch c = is.Peek();
+ codepoint <<= 4;
+ codepoint += static_cast<unsigned>(c);
+ if (c >= '0' && c <= '9')
+ codepoint -= '0';
+ else if (c >= 'A' && c <= 'F')
+ codepoint -= 'A' - 10;
+ else if (c >= 'a' && c <= 'f')
+ codepoint -= 'a' - 10;
+ else {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
+ }
+ is.Take();
+ }
+ return codepoint;
+ }
+
+ template <typename CharType>
+ class StackStream {
+ public:
+ typedef CharType Ch;
+
+ StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
+ RAPIDJSON_FORCEINLINE void Put(Ch c) {
+ *stack_.template Push<Ch>() = c;
+ ++length_;
+ }
+
+ RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
+ length_ += count;
+ return stack_.template Push<Ch>(count);
+ }
+
+ size_t Length() const { return length_; }
+
+ Ch* Pop() {
+ return stack_.template Pop<Ch>(length_);
+ }
+
+ private:
+ StackStream(const StackStream&);
+ StackStream& operator=(const StackStream&);
+
+ internal::Stack<StackAllocator>& stack_;
+ SizeType length_;
+ };
+
+ // Parse string and generate String event. Different code paths for kParseInsituFlag.
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ InputStream& s(copy.s);
+
+ RAPIDJSON_ASSERT(s.Peek() == '\"');
+ s.Take(); // Skip '\"'
+
+ bool success = false;
+ if (parseFlags & kParseInsituFlag) {
+ typename InputStream::Ch *head = s.PutBegin();
+ ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ size_t length = s.PutEnd(head) - 1;
+ RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+ const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
+ success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
+ }
+ else {
+ StackStream<typename TargetEncoding::Ch> stackStream(stack_);
+ ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
+ const typename TargetEncoding::Ch* const str = stackStream.Pop();
+ success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
+ }
+ if (RAPIDJSON_UNLIKELY(!success))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+ }
+
+ // Parse string to an output is
+ // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
+ template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ static const char escape[256] = {
+ Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
+ Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
+ 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
+ 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
+ };
+#undef Z16
+//!@endcond
+
+ for (;;) {
+ // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
+ if (!(parseFlags & kParseValidateEncodingFlag))
+ ScanCopyUnescapedString(is, os);
+
+ Ch c = is.Peek();
+ if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
+ size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
+ is.Take();
+ Ch e = is.Peek();
+ if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
+ is.Take();
+ os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
+ }
+ else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
+ is.Take();
+ unsigned codepoint = ParseHex4(is, escapeOffset);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
+ // Handle UTF-16 surrogate pair
+ if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
+ unsigned codepoint2 = ParseHex4(is, escapeOffset);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
+ codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
+ }
+ TEncoding::Encode(os, codepoint);
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
+ }
+ else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote
+ is.Take();
+ os.Put('\0'); // null-terminate the string
+ return;
+ }
+ else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+ if (c == '\0')
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell());
+ }
+ else {
+ size_t offset = is.Tell();
+ if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
+ !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
+ !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
+ }
+ }
+ }
+
+ template<typename InputStream, typename OutputStream>
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
+ // Do nothing for generic version
+ }
+
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+ // StringStream -> StackStream<char>
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
+ const char* p = is.src_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = p;
+ return;
+ }
+ else
+ os.Put(*p++);
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ SizeType length;
+ #ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+ #else
+ length = static_cast<SizeType>(__builtin_ffs(r) - 1);
+ #endif
+ char* q = reinterpret_cast<char*>(os.Push(length));
+ for (size_t i = 0; i < length; i++)
+ q[i] = p[i];
+
+ p += length;
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
+ }
+
+ is.src_ = p;
+ }
+
+ // InsituStringStream -> InsituStringStream
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
+ RAPIDJSON_ASSERT(&is == &os);
+ (void)os;
+
+ if (is.src_ == is.dst_) {
+ SkipUnescapedString(is);
+ return;
+ }
+
+ char* p = is.src_;
+ char *q = is.dst_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = p;
+ is.dst_ = q;
+ return;
+ }
+ else
+ *q++ = *p++;
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16, q += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ size_t length;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+#else
+ length = static_cast<size_t>(__builtin_ffs(r) - 1);
+#endif
+ for (const char* pend = p + length; p != pend; )
+ *q++ = *p++;
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
+ }
+
+ is.src_ = p;
+ is.dst_ = q;
+ }
+
+ // When read/write pointers are the same for insitu stream, just skip unescaped characters
+ static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
+ RAPIDJSON_ASSERT(is.src_ == is.dst_);
+ char* p = is.src_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ for (; p != nextAligned; p++)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = is.dst_ = p;
+ return;
+ }
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ size_t length;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+#else
+ length = static_cast<size_t>(__builtin_ffs(r) - 1);
+#endif
+ p += length;
+ break;
+ }
+ }
+
+ is.src_ = is.dst_ = p;
+ }
+#endif
+
+ template<typename InputStream, bool backup, bool pushOnTake>
+ class NumberStream;
+
+ template<typename InputStream>
+ class NumberStream<InputStream, false, false> {
+ public:
+ typedef typename InputStream::Ch Ch;
+
+ NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
+ RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
+ RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
+ RAPIDJSON_FORCEINLINE void Push(char) {}
+
+ size_t Tell() { return is.Tell(); }
+ size_t Length() { return 0; }
+ const char* Pop() { return 0; }
+
+ protected:
+ NumberStream& operator=(const NumberStream&);
+
+ InputStream& is;
+ };
+
+ template<typename InputStream>
+ class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
+ typedef NumberStream<InputStream, false, false> Base;
+ public:
+ NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch TakePush() {
+ stackStream.Put(static_cast<char>(Base::is.Peek()));
+ return Base::is.Take();
+ }
+
+ RAPIDJSON_FORCEINLINE void Push(char c) {
+ stackStream.Put(c);
+ }
+
+ size_t Length() { return stackStream.Length(); }
+
+ const char* Pop() {
+ stackStream.Put('\0');
+ return stackStream.Pop();
+ }
+
+ private:
+ StackStream<char> stackStream;
+ };
+
+ template<typename InputStream>
+ class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
+ typedef NumberStream<InputStream, true, false> Base;
+ public:
+ NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
+ };
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseNumber(InputStream& is, Handler& handler) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ NumberStream<InputStream,
+ ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
+ ((parseFlags & kParseInsituFlag) == 0) :
+ ((parseFlags & kParseFullPrecisionFlag) != 0),
+ (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
+ (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
+
+ size_t startOffset = s.Tell();
+ double d = 0.0;
+ bool useNanOrInf = false;
+
+ // Parse minus
+ bool minus = Consume(s, '-');
+
+ // Parse int: zero / ( digit1-9 *DIGIT )
+ unsigned i = 0;
+ uint64_t i64 = 0;
+ bool use64bit = false;
+ int significandDigit = 0;
+ if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
+ i = 0;
+ s.TakePush();
+ }
+ else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
+ i = static_cast<unsigned>(s.TakePush() - '0');
+
+ if (minus)
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
+ if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
+ i64 = i;
+ use64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ else
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
+ if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
+ i64 = i;
+ use64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ }
+ // Parse NaN or Infinity here
+ else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
+ useNanOrInf = true;
+ if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
+ d = std::numeric_limits<double>::quiet_NaN();
+ }
+ else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
+ d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
+ if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
+ && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+
+ // Parse 64bit int
+ bool useDouble = false;
+ if (use64bit) {
+ if (minus)
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
+ if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
+ d = static_cast<double>(i64);
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ else
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
+ if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
+ d = static_cast<double>(i64);
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ }
+
+ // Force double for big integer
+ if (useDouble) {
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
+ d = d * 10 + (s.TakePush() - '0');
+ }
+ }
+
+ // Parse frac = decimal-point 1*DIGIT
+ int expFrac = 0;
+ size_t decimalPosition;
+ if (Consume(s, '.')) {
+ decimalPosition = s.Length();
+
+ if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
+
+ if (!useDouble) {
+#if RAPIDJSON_64BIT
+ // Use i64 to store significand in 64-bit architecture
+ if (!use64bit)
+ i64 = i;
+
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
+ break;
+ else {
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ --expFrac;
+ if (i64 != 0)
+ significandDigit++;
+ }
+ }
+
+ d = static_cast<double>(i64);
+#else
+ // Use double to store significand in 32-bit architecture
+ d = static_cast<double>(use64bit ? i64 : i);
+#endif
+ useDouble = true;
+ }
+
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (significandDigit < 17) {
+ d = d * 10.0 + (s.TakePush() - '0');
+ --expFrac;
+ if (RAPIDJSON_LIKELY(d > 0.0))
+ significandDigit++;
+ }
+ else
+ s.TakePush();
+ }
+ }
+ else
+ decimalPosition = s.Length(); // decimal position at the end of integer.
+
+ // Parse exp = e [ minus / plus ] 1*DIGIT
+ int exp = 0;
+ if (Consume(s, 'e') || Consume(s, 'E')) {
+ if (!useDouble) {
+ d = static_cast<double>(use64bit ? i64 : i);
+ useDouble = true;
+ }
+
+ bool expMinus = false;
+ if (Consume(s, '+'))
+ ;
+ else if (Consume(s, '-'))
+ expMinus = true;
+
+ if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = static_cast<int>(s.Take() - '0');
+ if (expMinus) {
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = exp * 10 + static_cast<int>(s.Take() - '0');
+ if (exp >= 214748364) { // Issue #313: prevent overflow exponent
+ while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
+ s.Take();
+ }
+ }
+ }
+ else { // positive exp
+ int maxExp = 308 - expFrac;
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = exp * 10 + static_cast<int>(s.Take() - '0');
+ if (RAPIDJSON_UNLIKELY(exp > maxExp))
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
+ }
+ }
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
+
+ if (expMinus)
+ exp = -exp;
+ }
+
+ // Finish parsing, call event according to the type of number.
+ bool cont = true;
+
+ if (parseFlags & kParseNumbersAsStringsFlag) {
+ if (parseFlags & kParseInsituFlag) {
+ s.Pop(); // Pop stack no matter if it will be used or not.
+ typename InputStream::Ch* head = is.PutBegin();
+ const size_t length = s.Tell() - startOffset;
+ RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+ // unable to insert the \0 character here, it will erase the comma after this number
+ const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
+ cont = handler.RawNumber(str, SizeType(length), false);
+ }
+ else {
+ SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
+ StringStream srcStream(s.Pop());
+ StackStream<typename TargetEncoding::Ch> dstStream(stack_);
+ while (numCharsToCopy--) {
+ Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
+ }
+ dstStream.Put('\0');
+ const typename TargetEncoding::Ch* str = dstStream.Pop();
+ const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
+ cont = handler.RawNumber(str, SizeType(length), true);
+ }
+ }
+ else {
+ size_t length = s.Length();
+ const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
+
+ if (useDouble) {
+ int p = exp + expFrac;
+ if (parseFlags & kParseFullPrecisionFlag)
+ d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
+ else
+ d = internal::StrtodNormalPrecision(d, p);
+
+ cont = handler.Double(minus ? -d : d);
+ }
+ else if (useNanOrInf) {
+ cont = handler.Double(d);
+ }
+ else {
+ if (use64bit) {
+ if (minus)
+ cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
+ else
+ cont = handler.Uint64(i64);
+ }
+ else {
+ if (minus)
+ cont = handler.Int(static_cast<int32_t>(~i + 1));
+ else
+ cont = handler.Uint(i);
+ }
+ }
+ }
+ if (RAPIDJSON_UNLIKELY(!cont))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
+ }
+
+ // Parse any JSON value
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseValue(InputStream& is, Handler& handler) {
+ switch (is.Peek()) {
+ case 'n': ParseNull <parseFlags>(is, handler); break;
+ case 't': ParseTrue <parseFlags>(is, handler); break;
+ case 'f': ParseFalse <parseFlags>(is, handler); break;
+ case '"': ParseString<parseFlags>(is, handler); break;
+ case '{': ParseObject<parseFlags>(is, handler); break;
+ case '[': ParseArray <parseFlags>(is, handler); break;
+ default :
+ ParseNumber<parseFlags>(is, handler);
+ break;
+
+ }
+ }
+
+ // Iterative Parsing
+
+ // States
+ enum IterativeParsingState {
+ IterativeParsingStartState = 0,
+ IterativeParsingFinishState,
+ IterativeParsingErrorState,
+
+ // Object states
+ IterativeParsingObjectInitialState,
+ IterativeParsingMemberKeyState,
+ IterativeParsingKeyValueDelimiterState,
+ IterativeParsingMemberValueState,
+ IterativeParsingMemberDelimiterState,
+ IterativeParsingObjectFinishState,
+
+ // Array states
+ IterativeParsingArrayInitialState,
+ IterativeParsingElementState,
+ IterativeParsingElementDelimiterState,
+ IterativeParsingArrayFinishState,
+
+ // Single value state
+ IterativeParsingValueState
+ };
+
+ enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 };
+
+ // Tokens
+ enum Token {
+ LeftBracketToken = 0,
+ RightBracketToken,
+
+ LeftCurlyBracketToken,
+ RightCurlyBracketToken,
+
+ CommaToken,
+ ColonToken,
+
+ StringToken,
+ FalseToken,
+ TrueToken,
+ NullToken,
+ NumberToken,
+
+ kTokenCount
+ };
+
+ RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define N NumberToken
+#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
+ // Maps from ASCII to Token
+ static const unsigned char tokenMap[256] = {
+ N16, // 00~0F
+ N16, // 10~1F
+ N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
+ N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
+ N16, // 40~4F
+ N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
+ N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
+ N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
+ N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
+ };
+#undef N
+#undef N16
+//!@endcond
+
+ if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
+ return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
+ else
+ return NumberToken;
+ }
+
+ RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
+ // current state x one lookahead token -> new state
+ static const char G[cIterativeParsingStateCount][kTokenCount] = {
+ // Start
+ {
+ IterativeParsingArrayInitialState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingValueState, // String
+ IterativeParsingValueState, // False
+ IterativeParsingValueState, // True
+ IterativeParsingValueState, // Null
+ IterativeParsingValueState // Number
+ },
+ // Finish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // Error(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // ObjectInitial
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberKeyState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // MemberKey
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingKeyValueDelimiterState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // KeyValueDelimiter
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberValueState, // String
+ IterativeParsingMemberValueState, // False
+ IterativeParsingMemberValueState, // True
+ IterativeParsingMemberValueState, // Null
+ IterativeParsingMemberValueState // Number
+ },
+ // MemberValue
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingMemberDelimiterState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // MemberDelimiter
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberKeyState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // ObjectFinish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // ArrayInitial
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push Element state)
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingElementState, // String
+ IterativeParsingElementState, // False
+ IterativeParsingElementState, // True
+ IterativeParsingElementState, // Null
+ IterativeParsingElementState // Number
+ },
+ // Element
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingElementDelimiterState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // ElementDelimiter
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push Element state)
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingElementState, // String
+ IterativeParsingElementState, // False
+ IterativeParsingElementState, // True
+ IterativeParsingElementState, // Null
+ IterativeParsingElementState // Number
+ },
+ // ArrayFinish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // Single Value (sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ }
+ }; // End of G
+
+ return static_cast<IterativeParsingState>(G[state][token]);
+ }
+
+ // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
+ // May return a new state on state pop.
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
+ (void)token;
+
+ switch (dst) {
+ case IterativeParsingErrorState:
+ return dst;
+
+ case IterativeParsingObjectInitialState:
+ case IterativeParsingArrayInitialState:
+ {
+ // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
+ // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
+ IterativeParsingState n = src;
+ if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
+ n = IterativeParsingElementState;
+ else if (src == IterativeParsingKeyValueDelimiterState)
+ n = IterativeParsingMemberValueState;
+ // Push current state.
+ *stack_.template Push<SizeType>(1) = n;
+ // Initialize and push the member/element count.
+ *stack_.template Push<SizeType>(1) = 0;
+ // Call handler
+ bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return dst;
+ }
+ }
+
+ case IterativeParsingMemberKeyState:
+ ParseString<parseFlags>(is, handler, true);
+ if (HasParseError())
+ return IterativeParsingErrorState;
+ else
+ return dst;
+
+ case IterativeParsingKeyValueDelimiterState:
+ RAPIDJSON_ASSERT(token == ColonToken);
+ is.Take();
+ return dst;
+
+ case IterativeParsingMemberValueState:
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return dst;
+
+ case IterativeParsingElementState:
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return dst;
+
+ case IterativeParsingMemberDelimiterState:
+ case IterativeParsingElementDelimiterState:
+ is.Take();
+ // Update member/element count.
+ *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
+ return dst;
+
+ case IterativeParsingObjectFinishState:
+ {
+ // Transit from delimiter is only allowed when trailing commas are enabled
+ if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ // Get member count.
+ SizeType c = *stack_.template Pop<SizeType>(1);
+ // If the object is not empty, count the last member.
+ if (src == IterativeParsingMemberValueState)
+ ++c;
+ // Restore the state.
+ IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+ // Transit to Finish state if this is the topmost scope.
+ if (n == IterativeParsingStartState)
+ n = IterativeParsingFinishState;
+ // Call handler
+ bool hr = handler.EndObject(c);
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return n;
+ }
+ }
+
+ case IterativeParsingArrayFinishState:
+ {
+ // Transit from delimiter is only allowed when trailing commas are enabled
+ if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ // Get element count.
+ SizeType c = *stack_.template Pop<SizeType>(1);
+ // If the array is not empty, count the last element.
+ if (src == IterativeParsingElementState)
+ ++c;
+ // Restore the state.
+ IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+ // Transit to Finish state if this is the topmost scope.
+ if (n == IterativeParsingStartState)
+ n = IterativeParsingFinishState;
+ // Call handler
+ bool hr = handler.EndArray(c);
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return n;
+ }
+ }
+
+ default:
+ // This branch is for IterativeParsingValueState actually.
+ // Use `default:` rather than
+ // `case IterativeParsingValueState:` is for code coverage.
+
+ // The IterativeParsingStartState is not enumerated in this switch-case.
+ // It is impossible for that case. And it can be caught by following assertion.
+
+ // The IterativeParsingFinishState is not enumerated in this switch-case either.
+ // It is a "derivative" state which cannot triggered from Predict() directly.
+ // Therefore it cannot happen here. And it can be caught by following assertion.
+ RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
+
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return IterativeParsingFinishState;
+ }
+ }
+
+ template <typename InputStream>
+ void HandleError(IterativeParsingState src, InputStream& is) {
+ if (HasParseError()) {
+ // Error flag has been set.
+ return;
+ }
+
+ switch (src) {
+ case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
+ case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
+ case IterativeParsingObjectInitialState:
+ case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
+ case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
+ case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
+ case IterativeParsingKeyValueDelimiterState:
+ case IterativeParsingArrayInitialState:
+ case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
+ default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
+ }
+ }
+
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ ParseResult IterativeParse(InputStream& is, Handler& handler) {
+ parseResult_.Clear();
+ ClearStackOnExit scope(*this);
+ IterativeParsingState state = IterativeParsingStartState;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ while (is.Peek() != '\0') {
+ Token t = Tokenize(is.Peek());
+ IterativeParsingState n = Predict(state, t);
+ IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
+
+ if (d == IterativeParsingErrorState) {
+ HandleError(state, is);
+ break;
+ }
+
+ state = d;
+
+ // Do not further consume streams if a root JSON has been parsed.
+ if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
+ break;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+
+ // Handle the end of file.
+ if (state != IterativeParsingFinishState)
+ HandleError(state, is);
+
+ return parseResult_;
+ }
+
+ static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
+ internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
+ ParseResult parseResult_;
+}; // class GenericReader
+
+//! Reader with UTF8 encoding and default allocator.
+typedef GenericReader<UTF8<>, UTF8<> > Reader;
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_READER_H_
diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h
new file mode 100644
index 00000000..b182aa27
--- /dev/null
+++ b/include/rapidjson/schema.h
@@ -0,0 +1,2006 @@
+// Tencent is pleased to support the open source community by making RapidJSON available->
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved->
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License-> You may obtain a copy of the License at
+//
+// http://opensource->org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied-> See the License for the
+// specific language governing permissions and limitations under the License->
+
+#ifndef RAPIDJSON_SCHEMA_H_
+#define RAPIDJSON_SCHEMA_H_
+
+#include "document.h"
+#include "pointer.h"
+#include <cmath> // abs, floor
+
+#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
+#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
+#else
+#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
+#endif
+
+#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
+#define RAPIDJSON_SCHEMA_USE_STDREGEX 1
+#else
+#define RAPIDJSON_SCHEMA_USE_STDREGEX 0
+#endif
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+#include "internal/regex.h"
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+#include <regex>
+#endif
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX
+#define RAPIDJSON_SCHEMA_HAS_REGEX 1
+#else
+#define RAPIDJSON_SCHEMA_HAS_REGEX 0
+#endif
+
+#ifndef RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_SCHEMA_VERBOSE 0
+#endif
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#include "stringbuffer.h"
+#endif
+
+RAPIDJSON_DIAG_PUSH
+
+#if defined(__GNUC__)
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_OFF(weak-vtables)
+RAPIDJSON_DIAG_OFF(exit-time-destructors)
+RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
+RAPIDJSON_DIAG_OFF(variadic-macros)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Verbose Utilities
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+
+namespace internal {
+
+inline void PrintInvalidKeyword(const char* keyword) {
+ printf("Fail keyword: %s\n", keyword);
+}
+
+inline void PrintInvalidKeyword(const wchar_t* keyword) {
+ wprintf(L"Fail keyword: %ls\n", keyword);
+}
+
+inline void PrintInvalidDocument(const char* document) {
+ printf("Fail document: %s\n\n", document);
+}
+
+inline void PrintInvalidDocument(const wchar_t* document) {
+ wprintf(L"Fail document: %ls\n\n", document);
+}
+
+inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
+ printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
+}
+
+inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
+ wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
+}
+
+} // namespace internal
+
+#endif // RAPIDJSON_SCHEMA_VERBOSE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_INVALID_KEYWORD_RETURN
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
+#else
+#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
+#endif
+
+#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
+RAPIDJSON_MULTILINEMACRO_BEGIN\
+ context.invalidKeyword = keyword.GetString();\
+ RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\
+ return false;\
+RAPIDJSON_MULTILINEMACRO_END
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward declarations
+
+template <typename ValueType, typename Allocator>
+class GenericSchemaDocument;
+
+namespace internal {
+
+template <typename SchemaDocumentType>
+class Schema;
+
+///////////////////////////////////////////////////////////////////////////////
+// ISchemaValidator
+
+class ISchemaValidator {
+public:
+ virtual ~ISchemaValidator() {}
+ virtual bool IsValid() const = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ISchemaStateFactory
+
+template <typename SchemaType>
+class ISchemaStateFactory {
+public:
+ virtual ~ISchemaStateFactory() {}
+ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;
+ virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
+ virtual void* CreateHasher() = 0;
+ virtual uint64_t GetHashCode(void* hasher) = 0;
+ virtual void DestroryHasher(void* hasher) = 0;
+ virtual void* MallocState(size_t size) = 0;
+ virtual void FreeState(void* p) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Hasher
+
+// For comparison of compound value
+template<typename Encoding, typename Allocator>
+class Hasher {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
+
+ bool Null() { return WriteType(kNullType); }
+ bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
+ bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
+ bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
+ bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
+ bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
+ bool Double(double d) {
+ Number n;
+ if (d < 0) n.u.i = static_cast<int64_t>(d);
+ else n.u.u = static_cast<uint64_t>(d);
+ n.d = d;
+ return WriteNumber(n);
+ }
+
+ bool RawNumber(const Ch* str, SizeType len, bool) {
+ WriteBuffer(kNumberType, str, len * sizeof(Ch));
+ return true;
+ }
+
+ bool String(const Ch* str, SizeType len, bool) {
+ WriteBuffer(kStringType, str, len * sizeof(Ch));
+ return true;
+ }
+
+ bool StartObject() { return true; }
+ bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
+ bool EndObject(SizeType memberCount) {
+ uint64_t h = Hash(0, kObjectType);
+ uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
+ for (SizeType i = 0; i < memberCount; i++)
+ h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ bool StartArray() { return true; }
+ bool EndArray(SizeType elementCount) {
+ uint64_t h = Hash(0, kArrayType);
+ uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
+ for (SizeType i = 0; i < elementCount; i++)
+ h = Hash(h, e[i]); // Use hash to achieve element order sensitive
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }
+
+ uint64_t GetHashCode() const {
+ RAPIDJSON_ASSERT(IsValid());
+ return *stack_.template Top<uint64_t>();
+ }
+
+private:
+ static const size_t kDefaultSize = 256;
+ struct Number {
+ union U {
+ uint64_t u;
+ int64_t i;
+ }u;
+ double d;
+ };
+
+ bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }
+
+ bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }
+
+ bool WriteBuffer(Type type, const void* data, size_t len) {
+ // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/
+ uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
+ const unsigned char* d = static_cast<const unsigned char*>(data);
+ for (size_t i = 0; i < len; i++)
+ h = Hash(h, d[i]);
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ static uint64_t Hash(uint64_t h, uint64_t d) {
+ static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
+ h ^= d;
+ h *= kPrime;
+ return h;
+ }
+
+ Stack<Allocator> stack_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// SchemaValidationContext
+
+template <typename SchemaDocumentType>
+struct SchemaValidationContext {
+ typedef Schema<SchemaDocumentType> SchemaType;
+ typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
+ typedef typename SchemaType::ValueType ValueType;
+ typedef typename ValueType::Ch Ch;
+
+ enum PatternValidatorType {
+ kPatternValidatorOnly,
+ kPatternValidatorWithProperty,
+ kPatternValidatorWithAdditionalProperty
+ };
+
+ SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) :
+ factory(f),
+ schema(s),
+ valueSchema(),
+ invalidKeyword(),
+ hasher(),
+ arrayElementHashCodes(),
+ validators(),
+ validatorCount(),
+ patternPropertiesValidators(),
+ patternPropertiesValidatorCount(),
+ patternPropertiesSchemas(),
+ patternPropertiesSchemaCount(),
+ valuePatternValidatorType(kPatternValidatorOnly),
+ propertyExist(),
+ inArray(false),
+ valueUniqueness(false),
+ arrayUniqueness(false)
+ {
+ }
+
+ ~SchemaValidationContext() {
+ if (hasher)
+ factory.DestroryHasher(hasher);
+ if (validators) {
+ for (SizeType i = 0; i < validatorCount; i++)
+ factory.DestroySchemaValidator(validators[i]);
+ factory.FreeState(validators);
+ }
+ if (patternPropertiesValidators) {
+ for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
+ factory.DestroySchemaValidator(patternPropertiesValidators[i]);
+ factory.FreeState(patternPropertiesValidators);
+ }
+ if (patternPropertiesSchemas)
+ factory.FreeState(patternPropertiesSchemas);
+ if (propertyExist)
+ factory.FreeState(propertyExist);
+ }
+
+ SchemaValidatorFactoryType& factory;
+ const SchemaType* schema;
+ const SchemaType* valueSchema;
+ const Ch* invalidKeyword;
+ void* hasher; // Only validator access
+ void* arrayElementHashCodes; // Only validator access this
+ ISchemaValidator** validators;
+ SizeType validatorCount;
+ ISchemaValidator** patternPropertiesValidators;
+ SizeType patternPropertiesValidatorCount;
+ const SchemaType** patternPropertiesSchemas;
+ SizeType patternPropertiesSchemaCount;
+ PatternValidatorType valuePatternValidatorType;
+ PatternValidatorType objectPatternValidatorType;
+ SizeType arrayElementIndex;
+ bool* propertyExist;
+ bool inArray;
+ bool valueUniqueness;
+ bool arrayUniqueness;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Schema
+
+template <typename SchemaDocumentType>
+class Schema {
+public:
+ typedef typename SchemaDocumentType::ValueType ValueType;
+ typedef typename SchemaDocumentType::AllocatorType AllocatorType;
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+ typedef SchemaValidationContext<SchemaDocumentType> Context;
+ typedef Schema<SchemaDocumentType> SchemaType;
+ typedef GenericValue<EncodingType, AllocatorType> SValue;
+ friend class GenericSchemaDocument<ValueType, AllocatorType>;
+
+ Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
+ allocator_(allocator),
+ enum_(),
+ enumCount_(),
+ not_(),
+ type_((1 << kTotalSchemaType) - 1), // typeless
+ validatorCount_(),
+ properties_(),
+ additionalPropertiesSchema_(),
+ patternProperties_(),
+ patternPropertyCount_(),
+ propertyCount_(),
+ minProperties_(),
+ maxProperties_(SizeType(~0)),
+ additionalProperties_(true),
+ hasDependencies_(),
+ hasRequired_(),
+ hasSchemaDependencies_(),
+ additionalItemsSchema_(),
+ itemsList_(),
+ itemsTuple_(),
+ itemsTupleCount_(),
+ minItems_(),
+ maxItems_(SizeType(~0)),
+ additionalItems_(true),
+ uniqueItems_(false),
+ pattern_(),
+ minLength_(0),
+ maxLength_(~SizeType(0)),
+ exclusiveMinimum_(false),
+ exclusiveMaximum_(false)
+ {
+ typedef typename SchemaDocumentType::ValueType ValueType;
+ typedef typename ValueType::ConstValueIterator ConstValueIterator;
+ typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
+
+ if (!value.IsObject())
+ return;
+
+ if (const ValueType* v = GetMember(value, GetTypeString())) {
+ type_ = 0;
+ if (v->IsString())
+ AddType(*v);
+ else if (v->IsArray())
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
+ AddType(*itr);
+ }
+
+ if (const ValueType* v = GetMember(value, GetEnumString()))
+ if (v->IsArray() && v->Size() > 0) {
+ enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
+ typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
+ char buffer[256 + 24];
+ MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
+ EnumHasherType h(&hasherAllocator, 256);
+ itr->Accept(h);
+ enum_[enumCount_++] = h.GetHashCode();
+ }
+ }
+
+ if (schemaDocument) {
+ AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
+ AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
+ AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
+ }
+
+ if (const ValueType* v = GetMember(value, GetNotString())) {
+ schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document);
+ notValidatorIndex_ = validatorCount_;
+ validatorCount_++;
+ }
+
+ // Object
+
+ const ValueType* properties = GetMember(value, GetPropertiesString());
+ const ValueType* required = GetMember(value, GetRequiredString());
+ const ValueType* dependencies = GetMember(value, GetDependenciesString());
+ {
+ // Gather properties from properties/required/dependencies
+ SValue allProperties(kArrayType);
+
+ if (properties && properties->IsObject())
+ for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
+ AddUniqueElement(allProperties, itr->name);
+
+ if (required && required->IsArray())
+ for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
+ if (itr->IsString())
+ AddUniqueElement(allProperties, *itr);
+
+ if (dependencies && dependencies->IsObject())
+ for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
+ AddUniqueElement(allProperties, itr->name);
+ if (itr->value.IsArray())
+ for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
+ if (i->IsString())
+ AddUniqueElement(allProperties, *i);
+ }
+
+ if (allProperties.Size() > 0) {
+ propertyCount_ = allProperties.Size();
+ properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));
+ for (SizeType i = 0; i < propertyCount_; i++) {
+ new (&properties_[i]) Property();
+ properties_[i].name = allProperties[i];
+ properties_[i].schema = GetTypeless();
+ }
+ }
+ }
+
+ if (properties && properties->IsObject()) {
+ PointerType q = p.Append(GetPropertiesString(), allocator_);
+ for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
+ SizeType index;
+ if (FindPropertyIndex(itr->name, &index))
+ schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
+ }
+ }
+
+ if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
+ PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
+ patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
+ patternPropertyCount_ = 0;
+
+ for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
+ new (&patternProperties_[patternPropertyCount_]) PatternProperty();
+ patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
+ schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
+ patternPropertyCount_++;
+ }
+ }
+
+ if (required && required->IsArray())
+ for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
+ if (itr->IsString()) {
+ SizeType index;
+ if (FindPropertyIndex(*itr, &index)) {
+ properties_[index].required = true;
+ hasRequired_ = true;
+ }
+ }
+
+ if (dependencies && dependencies->IsObject()) {
+ PointerType q = p.Append(GetDependenciesString(), allocator_);
+ hasDependencies_ = true;
+ for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
+ SizeType sourceIndex;
+ if (FindPropertyIndex(itr->name, &sourceIndex)) {
+ if (itr->value.IsArray()) {
+ properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
+ std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
+ for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
+ SizeType targetIndex;
+ if (FindPropertyIndex(*targetItr, &targetIndex))
+ properties_[sourceIndex].dependencies[targetIndex] = true;
+ }
+ }
+ else if (itr->value.IsObject()) {
+ hasSchemaDependencies_ = true;
+ schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
+ properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
+ validatorCount_++;
+ }
+ }
+ }
+ }
+
+ if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
+ if (v->IsBool())
+ additionalProperties_ = v->GetBool();
+ else if (v->IsObject())
+ schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
+ }
+
+ AssignIfExist(minProperties_, value, GetMinPropertiesString());
+ AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
+
+ // Array
+ if (const ValueType* v = GetMember(value, GetItemsString())) {
+ PointerType q = p.Append(GetItemsString(), allocator_);
+ if (v->IsObject()) // List validation
+ schemaDocument->CreateSchema(&itemsList_, q, *v, document);
+ else if (v->IsArray()) { // Tuple validation
+ itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
+ SizeType index = 0;
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
+ schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
+ }
+ }
+
+ AssignIfExist(minItems_, value, GetMinItemsString());
+ AssignIfExist(maxItems_, value, GetMaxItemsString());
+
+ if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
+ if (v->IsBool())
+ additionalItems_ = v->GetBool();
+ else if (v->IsObject())
+ schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
+ }
+
+ AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
+
+ // String
+ AssignIfExist(minLength_, value, GetMinLengthString());
+ AssignIfExist(maxLength_, value, GetMaxLengthString());
+
+ if (const ValueType* v = GetMember(value, GetPatternString()))
+ pattern_ = CreatePattern(*v);
+
+ // Number
+ if (const ValueType* v = GetMember(value, GetMinimumString()))
+ if (v->IsNumber())
+ minimum_.CopyFrom(*v, *allocator_);
+
+ if (const ValueType* v = GetMember(value, GetMaximumString()))
+ if (v->IsNumber())
+ maximum_.CopyFrom(*v, *allocator_);
+
+ AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
+ AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
+
+ if (const ValueType* v = GetMember(value, GetMultipleOfString()))
+ if (v->IsNumber() && v->GetDouble() > 0.0)
+ multipleOf_.CopyFrom(*v, *allocator_);
+ }
+
+ ~Schema() {
+ if (allocator_) {
+ allocator_->Free(enum_);
+ }
+ if (properties_) {
+ for (SizeType i = 0; i < propertyCount_; i++)
+ properties_[i].~Property();
+ AllocatorType::Free(properties_);
+ }
+ if (patternProperties_) {
+ for (SizeType i = 0; i < patternPropertyCount_; i++)
+ patternProperties_[i].~PatternProperty();
+ AllocatorType::Free(patternProperties_);
+ }
+ AllocatorType::Free(itemsTuple_);
+#if RAPIDJSON_SCHEMA_HAS_REGEX
+ if (pattern_) {
+ pattern_->~RegexType();
+ allocator_->Free(pattern_);
+ }
+#endif
+ }
+
+ bool BeginValue(Context& context) const {
+ if (context.inArray) {
+ if (uniqueItems_)
+ context.valueUniqueness = true;
+
+ if (itemsList_)
+ context.valueSchema = itemsList_;
+ else if (itemsTuple_) {
+ if (context.arrayElementIndex < itemsTupleCount_)
+ context.valueSchema = itemsTuple_[context.arrayElementIndex];
+ else if (additionalItemsSchema_)
+ context.valueSchema = additionalItemsSchema_;
+ else if (additionalItems_)
+ context.valueSchema = GetTypeless();
+ else
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
+ }
+ else
+ context.valueSchema = GetTypeless();
+
+ context.arrayElementIndex++;
+ }
+ return true;
+ }
+
+ RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
+ if (context.patternPropertiesValidatorCount > 0) {
+ bool otherValid = false;
+ SizeType count = context.patternPropertiesValidatorCount;
+ if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
+ otherValid = context.patternPropertiesValidators[--count]->IsValid();
+
+ bool patternValid = true;
+ for (SizeType i = 0; i < count; i++)
+ if (!context.patternPropertiesValidators[i]->IsValid()) {
+ patternValid = false;
+ break;
+ }
+
+ if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
+ if (!patternValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+ else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
+ if (!patternValid || !otherValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+ else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+
+ if (enum_) {
+ const uint64_t h = context.factory.GetHashCode(context.hasher);
+ for (SizeType i = 0; i < enumCount_; i++)
+ if (enum_[i] == h)
+ goto foundEnum;
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
+ foundEnum:;
+ }
+
+ if (allOf_.schemas)
+ for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
+ if (!context.validators[i]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
+
+ if (anyOf_.schemas) {
+ for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
+ if (context.validators[i]->IsValid())
+ goto foundAny;
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
+ foundAny:;
+ }
+
+ if (oneOf_.schemas) {
+ bool oneValid = false;
+ for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
+ if (context.validators[i]->IsValid()) {
+ if (oneValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
+ else
+ oneValid = true;
+ }
+ if (!oneValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
+ }
+
+ if (not_ && context.validators[notValidatorIndex_]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
+
+ return true;
+ }
+
+ bool Null(Context& context) const {
+ if (!(type_ & (1 << kNullSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+ return CreateParallelValidator(context);
+ }
+
+ bool Bool(Context& context, bool) const {
+ if (!(type_ & (1 << kBooleanSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+ return CreateParallelValidator(context);
+ }
+
+ bool Int(Context& context, int i) const {
+ if (!CheckInt(context, i))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Uint(Context& context, unsigned u) const {
+ if (!CheckUint(context, u))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Int64(Context& context, int64_t i) const {
+ if (!CheckInt(context, i))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Uint64(Context& context, uint64_t u) const {
+ if (!CheckUint(context, u))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Double(Context& context, double d) const {
+ if (!(type_ & (1 << kNumberSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
+ return false;
+
+ if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
+ return false;
+
+ if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
+ return false;
+
+ return CreateParallelValidator(context);
+ }
+
+ bool String(Context& context, const Ch* str, SizeType length, bool) const {
+ if (!(type_ & (1 << kStringSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
+ SizeType count;
+ if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
+ if (count < minLength_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
+ if (count > maxLength_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
+ }
+ }
+
+ if (pattern_ && !IsPatternMatch(pattern_, str, length))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
+
+ return CreateParallelValidator(context);
+ }
+
+ bool StartObject(Context& context) const {
+ if (!(type_ & (1 << kObjectSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (hasDependencies_ || hasRequired_) {
+ context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
+ std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
+ }
+
+ if (patternProperties_) { // pre-allocate schema array
+ SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType
+ context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));
+ context.patternPropertiesSchemaCount = 0;
+ std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
+ }
+
+ return CreateParallelValidator(context);
+ }
+
+ bool Key(Context& context, const Ch* str, SizeType len, bool) const {
+ if (patternProperties_) {
+ context.patternPropertiesSchemaCount = 0;
+ for (SizeType i = 0; i < patternPropertyCount_; i++)
+ if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len))
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
+ }
+
+ SizeType index;
+ if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
+ if (context.patternPropertiesSchemaCount > 0) {
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
+ context.valueSchema = GetTypeless();
+ context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
+ }
+ else
+ context.valueSchema = properties_[index].schema;
+
+ if (context.propertyExist)
+ context.propertyExist[index] = true;
+
+ return true;
+ }
+
+ if (additionalPropertiesSchema_) {
+ if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
+ context.valueSchema = GetTypeless();
+ context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
+ }
+ else
+ context.valueSchema = additionalPropertiesSchema_;
+ return true;
+ }
+ else if (additionalProperties_) {
+ context.valueSchema = GetTypeless();
+ return true;
+ }
+
+ if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
+
+ return true;
+ }
+
+ bool EndObject(Context& context, SizeType memberCount) const {
+ if (hasRequired_)
+ for (SizeType index = 0; index < propertyCount_; index++)
+ if (properties_[index].required)
+ if (!context.propertyExist[index])
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
+
+ if (memberCount < minProperties_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
+
+ if (memberCount > maxProperties_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
+
+ if (hasDependencies_) {
+ for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
+ if (context.propertyExist[sourceIndex]) {
+ if (properties_[sourceIndex].dependencies) {
+ for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
+ if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex])
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
+ }
+ else if (properties_[sourceIndex].dependenciesSchema)
+ if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
+ }
+ }
+
+ return true;
+ }
+
+ bool StartArray(Context& context) const {
+ if (!(type_ & (1 << kArraySchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ context.arrayElementIndex = 0;
+ context.inArray = true;
+
+ return CreateParallelValidator(context);
+ }
+
+ bool EndArray(Context& context, SizeType elementCount) const {
+ context.inArray = false;
+
+ if (elementCount < minItems_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
+
+ if (elementCount > maxItems_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
+
+ return true;
+ }
+
+ // Generate functions for string literal according to Ch
+#define RAPIDJSON_STRING_(name, ...) \
+ static const ValueType& Get##name##String() {\
+ static const Ch s[] = { __VA_ARGS__, '\0' };\
+ static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\
+ return v;\
+ }
+
+ RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
+ RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
+ RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
+ RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
+ RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
+ RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
+ RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
+ RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
+ RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
+ RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
+ RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
+ RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
+ RAPIDJSON_STRING_(Not, 'n', 'o', 't')
+ RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
+ RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
+ RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
+ RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
+ RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
+ RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
+
+#undef RAPIDJSON_STRING_
+
+private:
+ enum SchemaValueType {
+ kNullSchemaType,
+ kBooleanSchemaType,
+ kObjectSchemaType,
+ kArraySchemaType,
+ kStringSchemaType,
+ kNumberSchemaType,
+ kIntegerSchemaType,
+ kTotalSchemaType
+ };
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+ typedef internal::GenericRegex<EncodingType> RegexType;
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+ typedef std::basic_regex<Ch> RegexType;
+#else
+ typedef char RegexType;
+#endif
+
+ struct SchemaArray {
+ SchemaArray() : schemas(), count() {}
+ ~SchemaArray() { AllocatorType::Free(schemas); }
+ const SchemaType** schemas;
+ SizeType begin; // begin index of context.validators
+ SizeType count;
+ };
+
+ static const SchemaType* GetTypeless() {
+ static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0);
+ return &typeless;
+ }
+
+ template <typename V1, typename V2>
+ void AddUniqueElement(V1& a, const V2& v) {
+ for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
+ if (*itr == v)
+ return;
+ V1 c(v, *allocator_);
+ a.PushBack(c, *allocator_);
+ }
+
+ static const ValueType* GetMember(const ValueType& value, const ValueType& name) {
+ typename ValueType::ConstMemberIterator itr = value.FindMember(name);
+ return itr != value.MemberEnd() ? &(itr->value) : 0;
+ }
+
+ static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {
+ if (const ValueType* v = GetMember(value, name))
+ if (v->IsBool())
+ out = v->GetBool();
+ }
+
+ static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {
+ if (const ValueType* v = GetMember(value, name))
+ if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
+ out = static_cast<SizeType>(v->GetUint64());
+ }
+
+ void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {
+ if (const ValueType* v = GetMember(value, name)) {
+ if (v->IsArray() && v->Size() > 0) {
+ PointerType q = p.Append(name, allocator_);
+ out.count = v->Size();
+ out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
+ memset(out.schemas, 0, sizeof(Schema*)* out.count);
+ for (SizeType i = 0; i < out.count; i++)
+ schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
+ out.begin = validatorCount_;
+ validatorCount_ += out.count;
+ }
+ }
+ }
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType& value) {
+ if (value.IsString()) {
+ RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString());
+ if (!r->IsValid()) {
+ r->~RegexType();
+ AllocatorType::Free(r);
+ r = 0;
+ }
+ return r;
+ }
+ return 0;
+ }
+
+ static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
+ return pattern->Search(str);
+ }
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType& value) {
+ if (value.IsString())
+ try {
+ return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
+ }
+ catch (const std::regex_error&) {
+ }
+ return 0;
+ }
+
+ static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
+ std::match_results<const Ch*> r;
+ return std::regex_search(str, str + length, r, *pattern);
+ }
+#else
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType&) { return 0; }
+
+ static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
+#endif // RAPIDJSON_SCHEMA_USE_STDREGEX
+
+ void AddType(const ValueType& type) {
+ if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
+ else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
+ else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
+ else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
+ else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
+ else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
+ else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
+ }
+
+ bool CreateParallelValidator(Context& context) const {
+ if (enum_ || context.arrayUniqueness)
+ context.hasher = context.factory.CreateHasher();
+
+ if (validatorCount_) {
+ RAPIDJSON_ASSERT(context.validators == 0);
+ context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
+ context.validatorCount = validatorCount_;
+
+ if (allOf_.schemas)
+ CreateSchemaValidators(context, allOf_);
+
+ if (anyOf_.schemas)
+ CreateSchemaValidators(context, anyOf_);
+
+ if (oneOf_.schemas)
+ CreateSchemaValidators(context, oneOf_);
+
+ if (not_)
+ context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
+
+ if (hasSchemaDependencies_) {
+ for (SizeType i = 0; i < propertyCount_; i++)
+ if (properties_[i].dependenciesSchema)
+ context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
+ }
+ }
+
+ return true;
+ }
+
+ void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {
+ for (SizeType i = 0; i < schemas.count; i++)
+ context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
+ }
+
+ // O(n)
+ bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
+ SizeType len = name.GetStringLength();
+ const Ch* str = name.GetString();
+ for (SizeType index = 0; index < propertyCount_; index++)
+ if (properties_[index].name.GetStringLength() == len &&
+ (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
+ {
+ *outIndex = index;
+ return true;
+ }
+ return false;
+ }
+
+ bool CheckInt(Context& context, int64_t i) const {
+ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull()) {
+ if (minimum_.IsInt64()) {
+ if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ }
+ else if (minimum_.IsUint64()) {
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()
+ }
+ else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!maximum_.IsNull()) {
+ if (maximum_.IsInt64()) {
+ if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ }
+ else if (maximum_.IsUint64())
+ /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64()
+ else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!multipleOf_.IsNull()) {
+ if (multipleOf_.IsUint64()) {
+ if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ }
+ else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool CheckUint(Context& context, uint64_t i) const {
+ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull()) {
+ if (minimum_.IsUint64()) {
+ if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ }
+ else if (minimum_.IsInt64())
+ /* do nothing */; // i >= 0 > minimum.Getint64()
+ else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!maximum_.IsNull()) {
+ if (maximum_.IsUint64()) {
+ if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ }
+ else if (maximum_.IsInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_
+ else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!multipleOf_.IsNull()) {
+ if (multipleOf_.IsUint64()) {
+ if (i % multipleOf_.GetUint64() != 0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ }
+ else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool CheckDoubleMinimum(Context& context, double d) const {
+ if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ return true;
+ }
+
+ bool CheckDoubleMaximum(Context& context, double d) const {
+ if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ return true;
+ }
+
+ bool CheckDoubleMultipleOf(Context& context, double d) const {
+ double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
+ double q = std::floor(a / b);
+ double r = a - q * b;
+ if (r > 0.0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ return true;
+ }
+
+ struct Property {
+ Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
+ ~Property() { AllocatorType::Free(dependencies); }
+ SValue name;
+ const SchemaType* schema;
+ const SchemaType* dependenciesSchema;
+ SizeType dependenciesValidatorIndex;
+ bool* dependencies;
+ bool required;
+ };
+
+ struct PatternProperty {
+ PatternProperty() : schema(), pattern() {}
+ ~PatternProperty() {
+ if (pattern) {
+ pattern->~RegexType();
+ AllocatorType::Free(pattern);
+ }
+ }
+ const SchemaType* schema;
+ RegexType* pattern;
+ };
+
+ AllocatorType* allocator_;
+ uint64_t* enum_;
+ SizeType enumCount_;
+ SchemaArray allOf_;
+ SchemaArray anyOf_;
+ SchemaArray oneOf_;
+ const SchemaType* not_;
+ unsigned type_; // bitmask of kSchemaType
+ SizeType validatorCount_;
+ SizeType notValidatorIndex_;
+
+ Property* properties_;
+ const SchemaType* additionalPropertiesSchema_;
+ PatternProperty* patternProperties_;
+ SizeType patternPropertyCount_;
+ SizeType propertyCount_;
+ SizeType minProperties_;
+ SizeType maxProperties_;
+ bool additionalProperties_;
+ bool hasDependencies_;
+ bool hasRequired_;
+ bool hasSchemaDependencies_;
+
+ const SchemaType* additionalItemsSchema_;
+ const SchemaType* itemsList_;
+ const SchemaType** itemsTuple_;
+ SizeType itemsTupleCount_;
+ SizeType minItems_;
+ SizeType maxItems_;
+ bool additionalItems_;
+ bool uniqueItems_;
+
+ RegexType* pattern_;
+ SizeType minLength_;
+ SizeType maxLength_;
+
+ SValue minimum_;
+ SValue maximum_;
+ SValue multipleOf_;
+ bool exclusiveMinimum_;
+ bool exclusiveMaximum_;
+};
+
+template<typename Stack, typename Ch>
+struct TokenHelper {
+ RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
+ *documentStack.template Push<Ch>() = '/';
+ char buffer[21];
+ size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
+ for (size_t i = 0; i < length; i++)
+ *documentStack.template Push<Ch>() = buffer[i];
+ }
+};
+
+// Partial specialized version for char to prevent buffer copying.
+template <typename Stack>
+struct TokenHelper<Stack, char> {
+ RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
+ if (sizeof(SizeType) == 4) {
+ char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
+ *buffer++ = '/';
+ const char* end = internal::u32toa(index, buffer);
+ documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
+ }
+ else {
+ char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
+ *buffer++ = '/';
+ const char* end = internal::u64toa(index, buffer);
+ documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
+ }
+ }
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// IGenericRemoteSchemaDocumentProvider
+
+template <typename SchemaDocumentType>
+class IGenericRemoteSchemaDocumentProvider {
+public:
+ typedef typename SchemaDocumentType::Ch Ch;
+
+ virtual ~IGenericRemoteSchemaDocumentProvider() {}
+ virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericSchemaDocument
+
+//! JSON schema document.
+/*!
+ A JSON schema document is a compiled version of a JSON schema.
+ It is basically a tree of internal::Schema.
+
+ \note This is an immutable class (i.e. its instance cannot be modified after construction).
+ \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding.
+ \tparam Allocator Allocator type for allocating memory of this document.
+*/
+template <typename ValueT, typename Allocator = CrtAllocator>
+class GenericSchemaDocument {
+public:
+ typedef ValueT ValueType;
+ typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType;
+ typedef Allocator AllocatorType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+ typedef internal::Schema<GenericSchemaDocument> SchemaType;
+ typedef GenericPointer<ValueType, Allocator> PointerType;
+ friend class internal::Schema<GenericSchemaDocument>;
+ template <typename, typename, typename>
+ friend class GenericSchemaValidator;
+
+ //! Constructor.
+ /*!
+ Compile a JSON document into schema document.
+
+ \param document A JSON document as source.
+ \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
+ \param allocator An optional allocator instance for allocating memory. Can be null.
+ */
+ explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
+ remoteProvider_(remoteProvider),
+ allocator_(allocator),
+ ownAllocator_(),
+ root_(),
+ schemaMap_(allocator, kInitialSchemaMapSize),
+ schemaRef_(allocator, kInitialSchemaRefSize)
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+
+ // Generate root schema, it will call CreateSchema() to create sub-schemas,
+ // And call AddRefSchema() if there are $ref.
+ CreateSchemaRecursive(&root_, PointerType(), document, document);
+
+ // Resolve $ref
+ while (!schemaRef_.Empty()) {
+ SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);
+ if (const SchemaType* s = GetSchema(refEntry->target)) {
+ if (refEntry->schema)
+ *refEntry->schema = s;
+
+ // Create entry in map if not exist
+ if (!GetSchema(refEntry->source)) {
+ new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);
+ }
+ }
+ refEntry->~SchemaRefEntry();
+ }
+
+ RAPIDJSON_ASSERT(root_ != 0);
+
+ schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
+ remoteProvider_(rhs.remoteProvider_),
+ allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ root_(rhs.root_),
+ schemaMap_(std::move(rhs.schemaMap_)),
+ schemaRef_(std::move(rhs.schemaRef_))
+ {
+ rhs.remoteProvider_ = 0;
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ }
+#endif
+
+ //! Destructor
+ ~GenericSchemaDocument() {
+ while (!schemaMap_.Empty())
+ schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
+
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ //! Get the root schema.
+ const SchemaType& GetRoot() const { return *root_; }
+
+private:
+ //! Prohibit copying
+ GenericSchemaDocument(const GenericSchemaDocument&);
+ //! Prohibit assignment
+ GenericSchemaDocument& operator=(const GenericSchemaDocument&);
+
+ struct SchemaRefEntry {
+ SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
+ PointerType source;
+ PointerType target;
+ const SchemaType** schema;
+ };
+
+ struct SchemaEntry {
+ SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
+ ~SchemaEntry() {
+ if (owned) {
+ schema->~SchemaType();
+ Allocator::Free(schema);
+ }
+ }
+ PointerType pointer;
+ SchemaType* schema;
+ bool owned;
+ };
+
+ void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
+ if (schema)
+ *schema = SchemaType::GetTypeless();
+
+ if (v.GetType() == kObjectType) {
+ const SchemaType* s = GetSchema(pointer);
+ if (!s)
+ CreateSchema(schema, pointer, v, document);
+
+ for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
+ CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);
+ }
+ else if (v.GetType() == kArrayType)
+ for (SizeType i = 0; i < v.Size(); i++)
+ CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);
+ }
+
+ void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
+ RAPIDJSON_ASSERT(pointer.IsValid());
+ if (v.IsObject()) {
+ if (!HandleRefSchema(pointer, schema, v, document)) {
+ SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);
+ new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);
+ if (schema)
+ *schema = s;
+ }
+ }
+ }
+
+ bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {
+ static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' };
+ static const ValueType kRefValue(kRefString, 4);
+
+ typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);
+ if (itr == v.MemberEnd())
+ return false;
+
+ if (itr->value.IsString()) {
+ SizeType len = itr->value.GetStringLength();
+ if (len > 0) {
+ const Ch* s = itr->value.GetString();
+ SizeType i = 0;
+ while (i < len && s[i] != '#') // Find the first #
+ i++;
+
+ if (i > 0) { // Remote reference, resolve immediately
+ if (remoteProvider_) {
+ if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) {
+ PointerType pointer(&s[i], len - i, allocator_);
+ if (pointer.IsValid()) {
+ if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
+ if (schema)
+ *schema = sc;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ else if (s[i] == '#') { // Local reference, defer resolution
+ PointerType pointer(&s[i], len - i, allocator_);
+ if (pointer.IsValid()) {
+ if (const ValueType* nv = pointer.Get(document))
+ if (HandleRefSchema(source, schema, *nv, document))
+ return true;
+
+ new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ const SchemaType* GetSchema(const PointerType& pointer) const {
+ for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
+ if (pointer == target->pointer)
+ return target->schema;
+ return 0;
+ }
+
+ PointerType GetPointer(const SchemaType* schema) const {
+ for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
+ if (schema == target->schema)
+ return target->pointer;
+ return PointerType();
+ }
+
+ static const size_t kInitialSchemaMapSize = 64;
+ static const size_t kInitialSchemaRefSize = 64;
+
+ IRemoteSchemaDocumentProviderType* remoteProvider_;
+ Allocator *allocator_;
+ Allocator *ownAllocator_;
+ const SchemaType* root_; //!< Root schema.
+ internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
+ internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref
+};
+
+//! GenericSchemaDocument using Value type.
+typedef GenericSchemaDocument<Value> SchemaDocument;
+//! IGenericRemoteSchemaDocumentProvider using SchemaDocument.
+typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericSchemaValidator
+
+//! JSON Schema Validator.
+/*!
+ A SAX style JSON schema validator.
+ It uses a \c GenericSchemaDocument to validate SAX events.
+ It delegates the incoming SAX events to an output handler.
+ The default output handler does nothing.
+ It can be reused multiple times by calling \c Reset().
+
+ \tparam SchemaDocumentType Type of schema document.
+ \tparam OutputHandler Type of output handler. Default handler does nothing.
+ \tparam StateAllocator Allocator for storing the internal validation states.
+*/
+template <
+ typename SchemaDocumentType,
+ typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
+ typename StateAllocator = CrtAllocator>
+class GenericSchemaValidator :
+ public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
+ public internal::ISchemaValidator
+{
+public:
+ typedef typename SchemaDocumentType::SchemaType SchemaType;
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename SchemaType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+
+ //! Constructor without output handler.
+ /*!
+ \param schemaDocument The schema document to conform to.
+ \param allocator Optional allocator for storing internal validation states.
+ \param schemaStackCapacity Optional initial capacity of schema path stack.
+ \param documentStackCapacity Optional initial capacity of document path stack.
+ */
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(schemaDocument.GetRoot()),
+ outputHandler_(GetNullHandler()),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(0)
+#endif
+ {
+ }
+
+ //! Constructor with output handler.
+ /*!
+ \param schemaDocument The schema document to conform to.
+ \param allocator Optional allocator for storing internal validation states.
+ \param schemaStackCapacity Optional initial capacity of schema path stack.
+ \param documentStackCapacity Optional initial capacity of document path stack.
+ */
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ OutputHandler& outputHandler,
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(schemaDocument.GetRoot()),
+ outputHandler_(outputHandler),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(0)
+#endif
+ {
+ }
+
+ //! Destructor.
+ ~GenericSchemaValidator() {
+ Reset();
+ RAPIDJSON_DELETE(ownStateAllocator_);
+ }
+
+ //! Reset the internal states.
+ void Reset() {
+ while (!schemaStack_.Empty())
+ PopSchema();
+ documentStack_.Clear();
+ valid_ = true;
+ }
+
+ //! Checks whether the current state is valid.
+ // Implementation of ISchemaValidator
+ virtual bool IsValid() const { return valid_; }
+
+ //! Gets the JSON pointer pointed to the invalid schema.
+ PointerType GetInvalidSchemaPointer() const {
+ return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema());
+ }
+
+ //! Gets the keyword of invalid schema.
+ const Ch* GetInvalidSchemaKeyword() const {
+ return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
+ }
+
+ //! Gets the JSON pointer pointed to the invalid value.
+ PointerType GetInvalidDocumentPointer() const {
+ return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
+ }
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
+RAPIDJSON_MULTILINEMACRO_BEGIN\
+ *documentStack_.template Push<Ch>() = '\0';\
+ documentStack_.template Pop<Ch>(1);\
+ internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
+RAPIDJSON_MULTILINEMACRO_END
+#else
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
+#endif
+
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
+ if (!valid_) return false; \
+ if (!BeginValue() || !CurrentSchema().method arg1) {\
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
+ return valid_ = false;\
+ }
+
+#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
+ for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
+ if (context->hasher)\
+ static_cast<HasherType*>(context->hasher)->method arg2;\
+ if (context->validators)\
+ for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
+ static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
+ if (context->patternPropertiesValidators)\
+ for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
+ static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
+ }
+
+#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
+ return valid_ = EndValue() && outputHandler_.method arg2
+
+#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
+ RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
+
+ bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext() ), ( )); }
+ bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
+ bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
+ bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
+ bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
+ bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
+ bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
+ bool RawNumber(const Ch* str, SizeType length, bool copy)
+ { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
+ bool String(const Ch* str, SizeType length, bool copy)
+ { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
+
+ bool StartObject() {
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
+ return valid_ = outputHandler_.StartObject();
+ }
+
+ bool Key(const Ch* str, SizeType len, bool copy) {
+ if (!valid_) return false;
+ AppendToken(str, len);
+ if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
+ return valid_ = outputHandler_.Key(str, len, copy);
+ }
+
+ bool EndObject(SizeType memberCount) {
+ if (!valid_) return false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
+ if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
+ }
+
+ bool StartArray() {
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
+ return valid_ = outputHandler_.StartArray();
+ }
+
+ bool EndArray(SizeType elementCount) {
+ if (!valid_) return false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
+ if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
+ }
+
+#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
+#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
+#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
+#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
+
+ // Implementation of ISchemaStateFactory<SchemaType>
+ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
+ return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root,
+#if RAPIDJSON_SCHEMA_VERBOSE
+ depth_ + 1,
+#endif
+ &GetStateAllocator());
+ }
+
+ virtual void DestroySchemaValidator(ISchemaValidator* validator) {
+ GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);
+ v->~GenericSchemaValidator();
+ StateAllocator::Free(v);
+ }
+
+ virtual void* CreateHasher() {
+ return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());
+ }
+
+ virtual uint64_t GetHashCode(void* hasher) {
+ return static_cast<HasherType*>(hasher)->GetHashCode();
+ }
+
+ virtual void DestroryHasher(void* hasher) {
+ HasherType* h = static_cast<HasherType*>(hasher);
+ h->~HasherType();
+ StateAllocator::Free(h);
+ }
+
+ virtual void* MallocState(size_t size) {
+ return GetStateAllocator().Malloc(size);
+ }
+
+ virtual void FreeState(void* p) {
+ return StateAllocator::Free(p);
+ }
+
+private:
+ typedef typename SchemaType::Context Context;
+ typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
+ typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
+
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ const SchemaType& root,
+#if RAPIDJSON_SCHEMA_VERBOSE
+ unsigned depth,
+#endif
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(root),
+ outputHandler_(GetNullHandler()),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(depth)
+#endif
+ {
+ }
+
+ StateAllocator& GetStateAllocator() {
+ if (!stateAllocator_)
+ stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator());
+ return *stateAllocator_;
+ }
+
+ bool BeginValue() {
+ if (schemaStack_.Empty())
+ PushSchema(root_);
+ else {
+ if (CurrentContext().inArray)
+ internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
+
+ if (!CurrentSchema().BeginValue(CurrentContext()))
+ return false;
+
+ SizeType count = CurrentContext().patternPropertiesSchemaCount;
+ const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
+ typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
+ bool valueUniqueness = CurrentContext().valueUniqueness;
+ if (CurrentContext().valueSchema)
+ PushSchema(*CurrentContext().valueSchema);
+
+ if (count > 0) {
+ CurrentContext().objectPatternValidatorType = patternValidatorType;
+ ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
+ SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
+ va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
+ for (SizeType i = 0; i < count; i++)
+ va[validatorCount++] = CreateSchemaValidator(*sa[i]);
+ }
+
+ CurrentContext().arrayUniqueness = valueUniqueness;
+ }
+ return true;
+ }
+
+ bool EndValue() {
+ if (!CurrentSchema().EndValue(CurrentContext()))
+ return false;
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+ GenericStringBuffer<EncodingType> sb;
+ schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
+
+ *documentStack_.template Push<Ch>() = '\0';
+ documentStack_.template Pop<Ch>(1);
+ internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
+#endif
+
+ uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;
+
+ PopSchema();
+
+ if (!schemaStack_.Empty()) {
+ Context& context = CurrentContext();
+ if (context.valueUniqueness) {
+ HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
+ if (!a)
+ CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
+ for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
+ if (itr->GetUint64() == h)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
+ a->PushBack(h, GetStateAllocator());
+ }
+ }
+
+ // Remove the last token of document pointer
+ while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
+ ;
+
+ return true;
+ }
+
+ void AppendToken(const Ch* str, SizeType len) {
+ documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters
+ *documentStack_.template PushUnsafe<Ch>() = '/';
+ for (SizeType i = 0; i < len; i++) {
+ if (str[i] == '~') {
+ *documentStack_.template PushUnsafe<Ch>() = '~';
+ *documentStack_.template PushUnsafe<Ch>() = '0';
+ }
+ else if (str[i] == '/') {
+ *documentStack_.template PushUnsafe<Ch>() = '~';
+ *documentStack_.template PushUnsafe<Ch>() = '1';
+ }
+ else
+ *documentStack_.template PushUnsafe<Ch>() = str[i];
+ }
+ }
+
+ RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, &schema); }
+
+ RAPIDJSON_FORCEINLINE void PopSchema() {
+ Context* c = schemaStack_.template Pop<Context>(1);
+ if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
+ a->~HashCodeArray();
+ StateAllocator::Free(a);
+ }
+ c->~Context();
+ }
+
+ const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
+ Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
+ const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
+
+ static OutputHandler& GetNullHandler() {
+ static OutputHandler nullHandler;
+ return nullHandler;
+ }
+
+ static const size_t kDefaultSchemaStackCapacity = 1024;
+ static const size_t kDefaultDocumentStackCapacity = 256;
+ const SchemaDocumentType* schemaDocument_;
+ const SchemaType& root_;
+ OutputHandler& outputHandler_;
+ StateAllocator* stateAllocator_;
+ StateAllocator* ownStateAllocator_;
+ internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
+ internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch)
+ bool valid_;
+#if RAPIDJSON_SCHEMA_VERBOSE
+ unsigned depth_;
+#endif
+};
+
+typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
+
+///////////////////////////////////////////////////////////////////////////////
+// SchemaValidatingReader
+
+//! A helper class for parsing with validation.
+/*!
+ This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate().
+
+ \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept.
+ \tparam SourceEncoding Encoding of the input stream.
+ \tparam SchemaDocumentType Type of schema document.
+ \tparam StackAllocator Allocator type for stack.
+*/
+template <
+ unsigned parseFlags,
+ typename InputStream,
+ typename SourceEncoding,
+ typename SchemaDocumentType = SchemaDocument,
+ typename StackAllocator = CrtAllocator>
+class SchemaValidatingReader {
+public:
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename InputStream::Ch Ch;
+
+ //! Constructor
+ /*!
+ \param is Input stream.
+ \param sd Schema document.
+ */
+ SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {}
+
+ template <typename Handler>
+ bool operator()(Handler& handler) {
+ GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader;
+ GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler);
+ parseResult_ = reader.template Parse<parseFlags>(is_, validator);
+
+ isValid_ = validator.IsValid();
+ if (isValid_) {
+ invalidSchemaPointer_ = PointerType();
+ invalidSchemaKeyword_ = 0;
+ invalidDocumentPointer_ = PointerType();
+ }
+ else {
+ invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
+ invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
+ invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
+ }
+
+ return parseResult_;
+ }
+
+ const ParseResult& GetParseResult() const { return parseResult_; }
+ bool IsValid() const { return isValid_; }
+ const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
+ const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
+ const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
+
+private:
+ InputStream& is_;
+ const SchemaDocumentType& sd_;
+
+ ParseResult parseResult_;
+ PointerType invalidSchemaPointer_;
+ const Ch* invalidSchemaKeyword_;
+ PointerType invalidDocumentPointer_;
+ bool isValid_;
+};
+
+RAPIDJSON_NAMESPACE_END
+RAPIDJSON_DIAG_POP
+
+#endif // RAPIDJSON_SCHEMA_H_
diff --git a/include/rapidjson/stream.h b/include/rapidjson/stream.h
new file mode 100644
index 00000000..fef82c25
--- /dev/null
+++ b/include/rapidjson/stream.h
@@ -0,0 +1,179 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#include "rapidjson.h"
+
+#ifndef RAPIDJSON_STREAM_H_
+#define RAPIDJSON_STREAM_H_
+
+#include "encodings.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Stream
+
+/*! \class rapidjson::Stream
+ \brief Concept for reading and writing characters.
+
+ For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
+
+ For write-only stream, only need to implement Put() and Flush().
+
+\code
+concept Stream {
+ typename Ch; //!< Character type of the stream.
+
+ //! Read the current character from stream without moving the read cursor.
+ Ch Peek() const;
+
+ //! Read the current character from stream and moving the read cursor to next character.
+ Ch Take();
+
+ //! Get the current read cursor.
+ //! \return Number of characters read from start.
+ size_t Tell();
+
+ //! Begin writing operation at the current read pointer.
+ //! \return The begin writer pointer.
+ Ch* PutBegin();
+
+ //! Write a character.
+ void Put(Ch c);
+
+ //! Flush the buffer.
+ void Flush();
+
+ //! End the writing operation.
+ //! \param begin The begin write pointer returned by PutBegin().
+ //! \return Number of characters written.
+ size_t PutEnd(Ch* begin);
+}
+\endcode
+*/
+
+//! Provides additional information for stream.
+/*!
+ By using traits pattern, this type provides a default configuration for stream.
+ For custom stream, this type can be specialized for other configuration.
+ See TEST(Reader, CustomStringStream) in readertest.cpp for example.
+*/
+template<typename Stream>
+struct StreamTraits {
+ //! Whether to make local copy of stream for optimization during parsing.
+ /*!
+ By default, for safety, streams do not use local copy optimization.
+ Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
+ */
+ enum { copyOptimization = 0 };
+};
+
+//! Reserve n characters for writing to a stream.
+template<typename Stream>
+inline void PutReserve(Stream& stream, size_t count) {
+ (void)stream;
+ (void)count;
+}
+
+//! Write character to a stream, presuming buffer is reserved.
+template<typename Stream>
+inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
+ stream.Put(c);
+}
+
+//! Put N copies of a character to a stream.
+template<typename Stream, typename Ch>
+inline void PutN(Stream& stream, Ch c, size_t n) {
+ PutReserve(stream, n);
+ for (size_t i = 0; i < n; i++)
+ PutUnsafe(stream, c);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream
+
+//! Read-only string stream.
+/*! \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringStream(const Ch *src) : src_(src), head_(src) {}
+
+ Ch Peek() const { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ const Ch* src_; //!< Current read position.
+ const Ch* head_; //!< Original head of the string.
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericStringStream<Encoding> > {
+ enum { copyOptimization = 1 };
+};
+
+//! String stream with UTF8 encoding.
+typedef GenericStringStream<UTF8<> > StringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// InsituStringStream
+
+//! A read-write string stream.
+/*! This string stream is particularly designed for in-situ parsing.
+ \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericInsituStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
+
+ // Read
+ Ch Peek() { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() { return static_cast<size_t>(src_ - head_); }
+
+ // Write
+ void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
+
+ Ch* PutBegin() { return dst_ = src_; }
+ size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
+ void Flush() {}
+
+ Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
+ void Pop(size_t count) { dst_ -= count; }
+
+ Ch* src_;
+ Ch* dst_;
+ Ch* head_;
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericInsituStringStream<Encoding> > {
+ enum { copyOptimization = 1 };
+};
+
+//! Insitu string stream with UTF8 encoding.
+typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STREAM_H_
diff --git a/include/rapidjson/stringbuffer.h b/include/rapidjson/stringbuffer.h
new file mode 100644
index 00000000..78f34d20
--- /dev/null
+++ b/include/rapidjson/stringbuffer.h
@@ -0,0 +1,117 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_STRINGBUFFER_H_
+#define RAPIDJSON_STRINGBUFFER_H_
+
+#include "stream.h"
+#include "internal/stack.h"
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+#include "internal/stack.h"
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output stream.
+/*!
+ \tparam Encoding Encoding of the stream.
+ \tparam Allocator type for allocating memory buffer.
+ \note implements Stream concept
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericStringBuffer {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
+ GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
+ if (&rhs != this)
+ stack_ = std::move(rhs.stack_);
+ return *this;
+ }
+#endif
+
+ void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+ void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; }
+ void Flush() {}
+
+ void Clear() { stack_.Clear(); }
+ void ShrinkToFit() {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.ShrinkToFit();
+ stack_.template Pop<Ch>(1);
+ }
+
+ void Reserve(size_t count) { stack_.template Reserve<Ch>(count); }
+ Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+ Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); }
+ void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+ const Ch* GetString() const {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.template Pop<Ch>(1);
+
+ return stack_.template Bottom<Ch>();
+ }
+
+ size_t GetSize() const { return stack_.GetSize(); }
+
+ static const size_t kDefaultCapacity = 256;
+ mutable internal::Stack<Allocator> stack_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ GenericStringBuffer(const GenericStringBuffer&);
+ GenericStringBuffer& operator=(const GenericStringBuffer&);
+};
+
+//! String buffer with UTF8 encoding
+typedef GenericStringBuffer<UTF8<> > StringBuffer;
+
+template<typename Encoding, typename Allocator>
+inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
+ stream.Reserve(count);
+}
+
+template<typename Encoding, typename Allocator>
+inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
+ stream.PutUnsafe(c);
+}
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
+ std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_STRINGBUFFER_H_
diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h
new file mode 100644
index 00000000..94f22dd5
--- /dev/null
+++ b/include/rapidjson/writer.h
@@ -0,0 +1,610 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_WRITER_H_
+#define RAPIDJSON_WRITER_H_
+
+#include "stream.h"
+#include "internal/stack.h"
+#include "internal/strfunc.h"
+#include "internal/dtoa.h"
+#include "internal/itoa.h"
+#include "stringbuffer.h"
+#include <new> // placement new
+
+#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+#endif
+#ifdef RAPIDJSON_SSE42
+#include <nmmintrin.h>
+#elif defined(RAPIDJSON_SSE2)
+#include <emmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(unreachable-code)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// WriteFlag
+
+/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-defined kWriteDefaultFlags definition.
+
+ User can define this as any \c WriteFlag combinations.
+*/
+#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
+#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
+#endif
+
+//! Combination of writeFlags
+enum WriteFlag {
+ kWriteNoFlags = 0, //!< No flags are set.
+ kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
+ kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
+ kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
+};
+
+//! JSON writer
+/*! Writer implements the concept Handler.
+ It generates JSON text by events to an output os.
+
+ User may programmatically calls the functions of a writer to generate JSON text.
+
+ On the other side, a writer can also be passed to objects that generates events,
+
+ for example Reader::Parse() and Document::Accept().
+
+ \tparam OutputStream Type of output stream.
+ \tparam SourceEncoding Encoding of source string.
+ \tparam TargetEncoding Encoding of output stream.
+ \tparam StackAllocator Type of allocator for allocating memory of stack.
+ \note implements Handler concept
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
+class Writer {
+public:
+ typedef typename SourceEncoding::Ch Ch;
+
+ static const int kDefaultMaxDecimalPlaces = 324;
+
+ //! Constructor
+ /*! \param os Output stream.
+ \param stackAllocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of stack.
+ */
+ explicit
+ Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
+
+ explicit
+ Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
+
+ //! Reset the writer with a new stream.
+ /*!
+ This function reset the writer with a new stream and default settings,
+ in order to make a Writer object reusable for output multiple JSONs.
+
+ \param os New output stream.
+ \code
+ Writer<OutputStream> writer(os1);
+ writer.StartObject();
+ // ...
+ writer.EndObject();
+
+ writer.Reset(os2);
+ writer.StartObject();
+ // ...
+ writer.EndObject();
+ \endcode
+ */
+ void Reset(OutputStream& os) {
+ os_ = &os;
+ hasRoot_ = false;
+ level_stack_.Clear();
+ }
+
+ //! Checks whether the output is a complete JSON.
+ /*!
+ A complete JSON has a complete root object or array.
+ */
+ bool IsComplete() const {
+ return hasRoot_ && level_stack_.Empty();
+ }
+
+ int GetMaxDecimalPlaces() const {
+ return maxDecimalPlaces_;
+ }
+
+ //! Sets the maximum number of decimal places for double output.
+ /*!
+ This setting truncates the output with specified number of decimal places.
+
+ For example,
+
+ \code
+ writer.SetMaxDecimalPlaces(3);
+ writer.StartArray();
+ writer.Double(0.12345); // "0.123"
+ writer.Double(0.0001); // "0.0"
+ writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent)
+ writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent)
+ writer.EndArray();
+ \endcode
+
+ The default setting does not truncate any decimal places. You can restore to this setting by calling
+ \code
+ writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
+ \endcode
+ */
+ void SetMaxDecimalPlaces(int maxDecimalPlaces) {
+ maxDecimalPlaces_ = maxDecimalPlaces;
+ }
+
+ /*!@name Implementation of Handler
+ \see Handler
+ */
+ //@{
+
+ bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
+ bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
+ bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
+ bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
+ bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
+ bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
+
+ //! Writes the given \c double value to the stream
+ /*!
+ \param d The value to be written.
+ \return Whether it is succeed.
+ */
+ bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
+
+ bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ Prefix(kNumberType);
+ return EndValue(WriteString(str, length));
+ }
+
+ bool String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ Prefix(kStringType);
+ return EndValue(WriteString(str, length));
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool String(const std::basic_string<Ch>& str) {
+ return String(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool StartObject() {
+ Prefix(kObjectType);
+ new (level_stack_.template Push<Level>()) Level(false);
+ return WriteStartObject();
+ }
+
+ bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ return EndValue(WriteEndObject());
+ }
+
+ bool StartArray() {
+ Prefix(kArrayType);
+ new (level_stack_.template Push<Level>()) Level(true);
+ return WriteStartArray();
+ }
+
+ bool EndArray(SizeType elementCount = 0) {
+ (void)elementCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ return EndValue(WriteEndArray());
+ }
+ //@}
+
+ /*! @name Convenience extensions */
+ //@{
+
+ //! Simpler but slower overload.
+ bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+ bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+ //@}
+
+ //! Write a raw JSON value.
+ /*!
+ For user to write a stringified JSON as a value.
+
+ \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
+ \param length Length of the json.
+ \param type Type of the root of json.
+ */
+ bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
+
+protected:
+ //! Information for each nested level
+ struct Level {
+ Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
+ size_t valueCount; //!< number of values in this level
+ bool inArray; //!< true if in array, otherwise in object
+ };
+
+ static const size_t kDefaultLevelDepth = 32;
+
+ bool WriteNull() {
+ PutReserve(*os_, 4);
+ PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
+ }
+
+ bool WriteBool(bool b) {
+ if (b) {
+ PutReserve(*os_, 4);
+ PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
+ }
+ else {
+ PutReserve(*os_, 5);
+ PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
+ }
+ return true;
+ }
+
+ bool WriteInt(int i) {
+ char buffer[11];
+ const char* end = internal::i32toa(i, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (const char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteUint(unsigned u) {
+ char buffer[10];
+ const char* end = internal::u32toa(u, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (const char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteInt64(int64_t i64) {
+ char buffer[21];
+ const char* end = internal::i64toa(i64, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (const char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteUint64(uint64_t u64) {
+ char buffer[20];
+ char* end = internal::u64toa(u64, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteDouble(double d) {
+ if (internal::Double(d).IsNanOrInf()) {
+ if (!(writeFlags & kWriteNanAndInfFlag))
+ return false;
+ if (internal::Double(d).IsNan()) {
+ PutReserve(*os_, 3);
+ PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
+ return true;
+ }
+ if (internal::Double(d).Sign()) {
+ PutReserve(*os_, 9);
+ PutUnsafe(*os_, '-');
+ }
+ else
+ PutReserve(*os_, 8);
+ PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
+ PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
+ return true;
+ }
+
+ char buffer[25];
+ char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteString(const Ch* str, SizeType length) {
+ static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ static const char escape[256] = {
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ //0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
+ 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
+ Z16, Z16, // 30~4F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
+#undef Z16
+ };
+
+ if (TargetEncoding::supportUnicode)
+ PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
+ else
+ PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
+
+ PutUnsafe(*os_, '\"');
+ GenericStringStream<SourceEncoding> is(str);
+ while (ScanWriteUnescapedString(is, length)) {
+ const Ch c = is.Peek();
+ if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
+ // Unicode escaping
+ unsigned codepoint;
+ if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
+ return false;
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, 'u');
+ if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
+ PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
+ // Surrogate pair
+ unsigned s = codepoint - 0x010000;
+ unsigned lead = (s >> 10) + 0xD800;
+ unsigned trail = (s & 0x3FF) + 0xDC00;
+ PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead ) & 15]);
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, 'u');
+ PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail ) & 15]);
+ }
+ }
+ else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
+ is.Take();
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
+ if (escape[static_cast<unsigned char>(c)] == 'u') {
+ PutUnsafe(*os_, '0');
+ PutUnsafe(*os_, '0');
+ PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
+ PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
+ }
+ }
+ else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
+ Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
+ Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
+ return false;
+ }
+ PutUnsafe(*os_, '\"');
+ return true;
+ }
+
+ bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+ }
+
+ bool WriteStartObject() { os_->Put('{'); return true; }
+ bool WriteEndObject() { os_->Put('}'); return true; }
+ bool WriteStartArray() { os_->Put('['); return true; }
+ bool WriteEndArray() { os_->Put(']'); return true; }
+
+ bool WriteRawValue(const Ch* json, size_t length) {
+ PutReserve(*os_, length);
+ for (size_t i = 0; i < length; i++) {
+ RAPIDJSON_ASSERT(json[i] != '\0');
+ PutUnsafe(*os_, json[i]);
+ }
+ return true;
+ }
+
+ void Prefix(Type type) {
+ (void)type;
+ if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
+ Level* level = level_stack_.template Top<Level>();
+ if (level->valueCount > 0) {
+ if (level->inArray)
+ os_->Put(','); // add comma if it is not the first element in array
+ else // in object
+ os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else {
+ RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
+ hasRoot_ = true;
+ }
+ }
+
+ // Flush the value if it is the top level one.
+ bool EndValue(bool ret) {
+ if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
+ os_->Flush();
+ return ret;
+ }
+
+ OutputStream* os_;
+ internal::Stack<StackAllocator> level_stack_;
+ int maxDecimalPlaces_;
+ bool hasRoot_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ Writer(const Writer&);
+ Writer& operator=(const Writer&);
+};
+
+// Full specialization for StringStream to prevent memory copying
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt(int i) {
+ char *buffer = os_->Push(11);
+ const char* end = internal::i32toa(i, buffer);
+ os_->Pop(static_cast<size_t>(11 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
+ char *buffer = os_->Push(10);
+ const char* end = internal::u32toa(u, buffer);
+ os_->Pop(static_cast<size_t>(10 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
+ char *buffer = os_->Push(21);
+ const char* end = internal::i64toa(i64, buffer);
+ os_->Pop(static_cast<size_t>(21 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
+ char *buffer = os_->Push(20);
+ const char* end = internal::u64toa(u, buffer);
+ os_->Pop(static_cast<size_t>(20 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteDouble(double d) {
+ if (internal::Double(d).IsNanOrInf()) {
+ // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
+ if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
+ return false;
+ if (internal::Double(d).IsNan()) {
+ PutReserve(*os_, 3);
+ PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
+ return true;
+ }
+ if (internal::Double(d).Sign()) {
+ PutReserve(*os_, 9);
+ PutUnsafe(*os_, '-');
+ }
+ else
+ PutReserve(*os_, 8);
+ PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
+ PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
+ return true;
+ }
+
+ char *buffer = os_->Push(25);
+ char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
+ os_->Pop(static_cast<size_t>(25 - (end - buffer)));
+ return true;
+}
+
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+template<>
+inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
+ if (length < 16)
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+
+ if (!RAPIDJSON_LIKELY(is.Tell() < length))
+ return false;
+
+ const char* p = is.src_;
+ const char* end = is.head_ + length;
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
+ if (nextAligned > end)
+ return true;
+
+ while (p != nextAligned)
+ if (*p < 0x20 || *p == '\"' || *p == '\\') {
+ is.src_ = p;
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+ }
+ else
+ os_->PutUnsafe(*p++);
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (; p != endAligned; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ SizeType len;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ len = offset;
+#else
+ len = static_cast<SizeType>(__builtin_ffs(r) - 1);
+#endif
+ char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
+ for (size_t i = 0; i < len; i++)
+ q[i] = p[i];
+
+ p += len;
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
+ }
+
+ is.src_ = p;
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+}
+#endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/include/smtp/SmtpMime b/include/smtp/SmtpMime
new file mode 100644
index 00000000..940996b8
--- /dev/null
+++ b/include/smtp/SmtpMime
@@ -0,0 +1,31 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef SMTPMIME_H
+#define SMTPMIME_H
+
+#include "smtpclient.h"
+#include "mimepart.h"
+#include "mimehtml.h"
+#include "mimeattachment.h"
+#include "mimemessage.h"
+#include "mimetext.h"
+#include "mimeinlinefile.h"
+#include "mimefile.h"
+
+#endif // SMTPMIME_H
diff --git a/include/smtp/emailaddress.h b/include/smtp/emailaddress.h
new file mode 100644
index 00000000..90e4c1e9
--- /dev/null
+++ b/include/smtp/emailaddress.h
@@ -0,0 +1,63 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef EMAILADDRESS_H
+#define EMAILADDRESS_H
+
+#include <QObject>
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT EmailAddress : public QObject {
+Q_OBJECT
+public:
+
+ /* [1] Constructors and Destructors */
+
+ EmailAddress() = default;
+
+ explicit EmailAddress(const QString &address, const QString &name = "");
+
+ ~EmailAddress() override;
+
+ /* [1] --- */
+
+
+ /* [2] Getters and Setters */
+ void setName(const QString &name);
+
+ void setAddress(const QString &address);
+
+ [[nodiscard]] const QString &getName() const;
+
+ [[nodiscard]] const QString &getAddress() const;
+
+ /* [2] --- */
+
+
+private:
+
+ /* [3] Private members */
+
+ QString name;
+ QString address;
+
+ /* [3] --- */
+};
+
+#endif // EMAILADDRESS_H
diff --git a/include/smtp/mimeattachment.h b/include/smtp/mimeattachment.h
new file mode 100644
index 00000000..6b98a65a
--- /dev/null
+++ b/include/smtp/mimeattachment.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMEATTACHMENT_H
+#define MIMEATTACHMENT_H
+
+#include <QFile>
+#include "mimepart.h"
+#include "mimefile.h"
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimeAttachment : public MimeFile {
+Q_OBJECT
+public:
+
+ /* [1] Constructors and Destructors */
+
+ explicit MimeAttachment(QFile *file);
+
+ MimeAttachment(const QByteArray &stream, const QString &fileName);
+
+ ~MimeAttachment() override;
+
+ /* [1] --- */
+
+protected:
+
+ /* [2] Protected methods */
+
+ void prepare() override;
+
+ /* [2] --- */
+};
+
+#endif // MIMEATTACHMENT_H
diff --git a/include/smtp/mimecontentformatter.h b/include/smtp/mimecontentformatter.h
new file mode 100644
index 00000000..e6e3637f
--- /dev/null
+++ b/include/smtp/mimecontentformatter.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMECONTENTFORMATTER_H
+#define MIMECONTENTFORMATTER_H
+
+#include <QObject>
+#include <QByteArray>
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimeContentFormatter : public QObject {
+Q_OBJECT
+public:
+ explicit MimeContentFormatter(int max_length = 76);
+
+ void setMaxLength(int l);
+
+ [[nodiscard]] int getMaxLength() const;
+
+ [[nodiscard]] QString format(const QString &content, bool quotedPrintable = false) const;
+
+protected:
+ int max_length;
+
+};
+
+#endif // MIMECONTENTFORMATTER_H
diff --git a/include/smtp/mimefile.h b/include/smtp/mimefile.h
new file mode 100644
index 00000000..46903da9
--- /dev/null
+++ b/include/smtp/mimefile.h
@@ -0,0 +1,63 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMEFILE_H
+#define MIMEFILE_H
+
+#include "mimepart.h"
+#include <QFile>
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimeFile : public MimePart {
+Q_OBJECT
+public:
+
+ /* [1] Constructors and Destructors */
+
+ MimeFile(const QByteArray &stream, const QString &fileName);
+
+ explicit MimeFile(QFile *f);
+
+ ~MimeFile() override;
+
+ /* [1] --- */
+
+
+ /* [2] Getters and Setters */
+
+ /* [2] --- */
+
+protected:
+
+ /* [3] Protected members */
+
+ QFile *file;
+
+ /* [3] --- */
+
+
+ /* [4] Protected methods */
+
+ void prepare() override;
+
+ /* [4] --- */
+
+};
+
+#endif // MIMEFILE_H
diff --git a/include/smtp/mimehtml.h b/include/smtp/mimehtml.h
new file mode 100644
index 00000000..8ce8c454
--- /dev/null
+++ b/include/smtp/mimehtml.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMEHTML_H
+#define MIMEHTML_H
+
+#include "mimetext.h"
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimeHtml : public MimeText {
+Q_OBJECT
+public:
+
+ /* [1] Constructors and Destructors */
+
+ explicit MimeHtml(const QString &html = "");
+
+ ~MimeHtml() override;
+
+ /* [1] --- */
+
+
+ /* [2] Getters and Setters */
+
+ void setHtml(const QString &html);
+
+ [[nodiscard]] const QString &getHtml() const;
+
+ /* [2] --- */
+
+protected:
+
+ /* [3] Protected members */
+
+ /* [3] --- */
+
+
+ /* [4] Protected methods */
+
+ void prepare() override;
+
+ /* [4] --- */
+};
+
+#endif // MIMEHTML_H
diff --git a/include/smtp/mimeinlinefile.h b/include/smtp/mimeinlinefile.h
new file mode 100644
index 00000000..916f7b76
--- /dev/null
+++ b/include/smtp/mimeinlinefile.h
@@ -0,0 +1,56 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMEINLINEFILE_H
+#define MIMEINLINEFILE_H
+
+#include "mimefile.h"
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimeInlineFile : public MimeFile {
+public:
+
+ /* [1] Constructors and Destructors */
+
+ explicit MimeInlineFile(QFile *f);
+
+ ~MimeInlineFile() override;
+
+ /* [1] --- */
+
+
+ /* [2] Getters and Setters */
+
+ /* [2] --- */
+
+protected:
+
+ /* [3] Protected members */
+
+ /* [3] --- */
+
+
+ /* [4] Protected methods */
+
+ void prepare() override;
+
+ /* [4] --- */
+};
+
+#endif // MIMEINLINEFILE_H
diff --git a/include/smtp/mimemessage.h b/include/smtp/mimemessage.h
new file mode 100644
index 00000000..24e4f108
--- /dev/null
+++ b/include/smtp/mimemessage.h
@@ -0,0 +1,110 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMEMESSAGE_H
+#define MIMEMESSAGE_H
+
+#include "mimepart.h"
+#include "mimemultipart.h"
+#include "emailaddress.h"
+#include <QList>
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimeMessage : public QObject {
+public:
+
+ enum RecipientType {
+ To, // primary
+ Cc, // carbon copy
+ Bcc // blind carbon copy
+ };
+
+ /* [1] Constructors and Destructors */
+
+ explicit MimeMessage(bool createAutoMimeConent = true);
+
+ ~MimeMessage() override;
+
+ /* [1] --- */
+
+
+ /* [2] Getters and Setters */
+
+ void setSender(EmailAddress *e);
+
+ void addRecipient(EmailAddress *rcpt, RecipientType type = To);
+
+ void addTo(EmailAddress *rcpt);
+
+ void addCc(EmailAddress *rcpt);
+
+ void addBcc(EmailAddress *rcpt);
+
+ void setSubject(const QString &subject);
+
+ void addPart(MimePart *part);
+
+ void setReplyTo(EmailAddress *rto);
+
+ void setInReplyTo(const QString &inReplyTo);
+
+ void setHeaderEncoding(MimePart::Encoding);
+
+ [[nodiscard]] const EmailAddress &getSender() const;
+
+ [[nodiscard]] const QList<EmailAddress *> &getRecipients(RecipientType type = To) const;
+
+ [[nodiscard]] const QString &getSubject() const;
+
+ [[nodiscard]] const QList<MimePart *> &getParts() const;
+
+ [[nodiscard]] const EmailAddress *getReplyTo() const;
+
+ MimePart &getContent();
+
+ void setContent(MimePart *content);
+ /* [2] --- */
+
+
+ /* [3] Public methods */
+
+ virtual QString toString();
+
+ /* [3] --- */
+
+protected:
+
+ /* [4] Protected members */
+
+ EmailAddress *sender{};
+ EmailAddress *replyTo;
+ QList<EmailAddress *> recipientsTo, recipientsCc, recipientsBcc;
+ QString subject;
+ QString mInReplyTo;
+ MimePart *content;
+ bool autoMimeContentCreated;
+
+ MimePart::Encoding hEncoding;
+
+ /* [4] --- */
+
+
+};
+
+#endif // MIMEMESSAGE_H
diff --git a/include/smtp/mimemultipart.h b/include/smtp/mimemultipart.h
new file mode 100644
index 00000000..b829a66f
--- /dev/null
+++ b/include/smtp/mimemultipart.h
@@ -0,0 +1,71 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMEMULTIPART_H
+#define MIMEMULTIPART_H
+
+#include "mimepart.h"
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimeMultiPart : public MimePart {
+Q_OBJECT
+public:
+ /* [0] Enums */
+ enum MultiPartType {
+ Mixed = 0, // RFC 2046, section 5.1.3
+ Digest = 1, // RFC 2046, section 5.1.5
+ Alternative = 2, // RFC 2046, section 5.1.4
+ Related = 3, // RFC 2387
+ Report = 4, // RFC 6522
+ Signed = 5, // RFC 1847, section 2.1
+ Encrypted = 6 // RFC 1847, section 2.2
+ };
+
+ /* [0] --- */
+
+ /* [1] Constructors and Destructors */
+ explicit MimeMultiPart(MultiPartType type = Related);
+
+ /* [1] --- */
+
+ /* [2] Getters and Setters */
+
+ void setMimeType(MultiPartType type);
+
+ [[nodiscard]] MultiPartType getMimeType() const;
+
+ [[nodiscard]] const QList<MimePart *> &getParts() const;
+
+ /* [2] --- */
+
+ /* [3] Public methods */
+
+ void addPart(MimePart *part);
+
+ void prepare() override;
+
+ /* [3] --- */
+
+protected:
+ QList<MimePart *> parts;
+
+ MultiPartType type;
+};
+
+#endif // MIMEMULTIPART_H
diff --git a/include/smtp/mimepart.h b/include/smtp/mimepart.h
new file mode 100644
index 00000000..1a1386de
--- /dev/null
+++ b/include/smtp/mimepart.h
@@ -0,0 +1,110 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMEPART_H
+#define MIMEPART_H
+
+#include "mimecontentformatter.h"
+#include <QObject>
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimePart : public QObject {
+Q_OBJECT
+public:
+ /* [0] Enumerations */
+ enum Encoding {
+ _7Bit, _8Bit, Base64, QuotedPrintable
+ };
+
+ /* [0] --- */
+
+ /* [1] Constructors and Destructors */
+
+ MimePart();
+
+ ~MimePart() = default;
+
+ /* [1] --- */
+
+ /* [2] Getters and Setters */
+
+ [[nodiscard]] const QString &getHeader() const;
+
+ [[nodiscard]] const QByteArray &getContent() const;
+
+ void setContent(const QByteArray &content);
+
+ void setHeader(const QString &header);
+
+ void addHeaderLine(const QString &line);
+
+ void setContentId(const QString &cId);
+
+ [[nodiscard]] const QString &getContentId() const;
+
+ void setContentName(const QString &cName);
+
+ [[nodiscard]] const QString &getContentName() const;
+
+ void setContentType(const QString &cType);
+
+ [[nodiscard]] const QString &getContentType() const;
+
+ void setCharset(const QString &charset);
+
+ [[nodiscard]] const QString &getCharset() const;
+
+ void setEncoding(Encoding enc);
+
+ [[nodiscard]] Encoding getEncoding() const;
+
+ MimeContentFormatter &getContentFormatter();
+
+ /* [2] --- */
+
+ /* [3] Public methods */
+
+ virtual QString toString();
+
+ virtual void prepare();
+
+ /* [3] --- */
+
+protected:
+ /* [4] Protected members */
+
+ QString header;
+ QByteArray content;
+
+ QString cId;
+ QString cName;
+ QString cType;
+ QString cCharset;
+ QString cBoundary;
+ Encoding cEncoding;
+
+ QString mimeString;
+ bool prepared;
+
+ MimeContentFormatter formatter;
+
+ /* [4] --- */
+};
+
+#endif // MIMEPART_H
diff --git a/include/smtp/mimetext.h b/include/smtp/mimetext.h
new file mode 100644
index 00000000..c21a1c5e
--- /dev/null
+++ b/include/smtp/mimetext.h
@@ -0,0 +1,62 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef MIMETEXT_H
+#define MIMETEXT_H
+
+#include "mimepart.h"
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT MimeText : public MimePart {
+public:
+
+ /* [1] Constructors and Destructors */
+
+ explicit MimeText(const QString &text = "");
+
+ ~MimeText() override;
+
+ /* [1] --- */
+
+
+ /* [2] Getters and Setters*/
+
+ void setText(const QString &text);
+
+ [[nodiscard]] const QString &getText() const;
+
+ /* [2] --- */
+
+protected:
+
+ /* [3] Protected members */
+
+ QString text;
+ /* [3] --- */
+
+
+ /* [4] Protected methods */
+
+ void prepare() override;
+
+ /* [4] --- */
+
+};
+
+#endif // MIMETEXT_H
diff --git a/include/smtp/quotedprintable.h b/include/smtp/quotedprintable.h
new file mode 100644
index 00000000..00ca3cf8
--- /dev/null
+++ b/include/smtp/quotedprintable.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef QUOTEDPRINTABLE_H
+#define QUOTEDPRINTABLE_H
+
+#include <QObject>
+#include <QByteArray>
+
+#include "smtpexports.h"
+
+class SMTP_EXPORT QuotedPrintable : public QObject {
+Q_OBJECT
+public:
+
+ static QString encode(const QByteArray &input);
+
+ static QByteArray decode(const QString &input);
+
+private:
+ QuotedPrintable();
+};
+
+#endif // QUOTEDPRINTABLE_H
diff --git a/include/smtp/smtpclient.h b/include/smtp/smtpclient.h
new file mode 100644
index 00000000..29c507dc
--- /dev/null
+++ b/include/smtp/smtpclient.h
@@ -0,0 +1,197 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#ifndef SMTPCLIENT_H
+#define SMTPCLIENT_H
+
+#include <QObject>
+#include <QtNetwork/QSslSocket>
+
+#include "mimemessage.h"
+#include "smtpexports.h"
+
+class SMTP_EXPORT SmtpClient : public QObject {
+Q_OBJECT
+public:
+
+ /* [0] Enumerations */
+
+ enum AuthMethod {
+ AuthPlain,
+ AuthLogin
+ };
+
+ enum SmtpError {
+ ConnectionTimeoutError,
+ ResponseTimeoutError,
+ SendDataTimeoutError,
+ AuthenticationFailedError,
+ ServerError, // 4xx smtp error
+ ClientError // 5xx smtp error
+ };
+
+ enum ConnectionType {
+ TcpConnection,
+ SslConnection,
+ TlsConnection // STARTTLS
+ };
+
+ /* [0] --- */
+
+
+ /* [1] Constructors and Destructors */
+
+ explicit SmtpClient(const QString &host = "localhost", int port = 25, ConnectionType ct = TcpConnection);
+
+ ~SmtpClient() override;
+
+ /* [1] --- */
+
+
+ /* [2] Getters and Setters */
+
+ [[nodiscard]] const QString &getHost() const;
+
+ void setHost(const QString &host);
+
+ [[nodiscard]] int getPort() const;
+
+ void setPort(int port);
+
+ [[nodiscard]] const QString &getName() const;
+
+ void setName(const QString &name);
+
+ [[nodiscard]] ConnectionType getConnectionType() const;
+
+ void setConnectionType(ConnectionType ct);
+
+ [[nodiscard]] const QString &getUser() const;
+
+ void setUser(const QString &user);
+
+ [[nodiscard]] const QString &getPassword() const;
+
+ void setPassword(const QString &password);
+
+ [[nodiscard]] SmtpClient::AuthMethod getAuthMethod() const;
+
+ void setAuthMethod(AuthMethod method);
+
+ [[nodiscard]] const QString &getResponseText() const;
+
+ [[nodiscard]] int getResponseCode() const;
+
+ [[nodiscard]] int getConnectionTimeout() const;
+
+ void setConnectionTimeout(int msec);
+
+ [[nodiscard]] int getResponseTimeout() const;
+
+ void setResponseTimeout(int msec);
+
+ [[nodiscard]] int getSendMessageTimeout() const;
+
+ void setSendMessageTimeout(int msec);
+
+ QTcpSocket *getSocket();
+
+
+ /* [2] --- */
+
+
+ /* [3] Public methods */
+
+ bool connectToHost();
+
+ bool login();
+
+ bool login(const QString &user, const QString &password, AuthMethod method = AuthLogin);
+
+ bool sendMail(MimeMessage &email);
+
+ void quit();
+
+
+ /* [3] --- */
+
+protected:
+
+ /* [4] Protected members */
+
+ QTcpSocket *socket;
+
+ QString host;
+ int port;
+ ConnectionType connectionType;
+ QString name;
+
+ QString user;
+ QString password;
+ AuthMethod authMethod;
+
+ int connectionTimeout;
+ int responseTimeout;
+ int sendMessageTimeout;
+
+
+ QString responseText;
+ int responseCode;
+
+
+ class ResponseTimeoutException : public std::exception {
+ };
+
+ class SendMessageTimeoutException : public std::exception {
+ };
+
+ /* [4] --- */
+
+
+ /* [5] Protected methods */
+
+ void waitForResponse();
+
+ void sendMessage(const QString &text);
+
+ /* [5] --- */
+
+protected slots:
+
+ /* [6] Protected slots */
+
+ void socketStateChanged(QAbstractSocket::SocketState state);
+
+ void socketError(QAbstractSocket::SocketError error);
+
+ void socketReadyRead();
+
+ /* [6] --- */
+
+
+signals:
+
+ /* [7] Signals */
+
+ void smtpError(SmtpClient::SmtpError e);
+
+ /* [7] --- */
+
+};
+
+#endif // SMTPCLIENT_H
diff --git a/include/smtp/smtpexports.h b/include/smtp/smtpexports.h
new file mode 100644
index 00000000..9ca12bae
--- /dev/null
+++ b/include/smtp/smtpexports.h
@@ -0,0 +1,10 @@
+#ifndef SMTPEXPORTS_H
+#define SMTPEXPORTS_H
+
+#ifdef SMTP_BUILD
+#define SMTP_EXPORT
+#else
+#define SMTP_EXPORT
+#endif
+
+#endif // SMTPEXPORTS_H
diff --git a/include/ui/AttachmentTableModel.h b/include/ui/AttachmentTableModel.h
deleted file mode 100644
index 9bc22cea..00000000
--- a/include/ui/AttachmentTableModel.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-#ifndef __ATTACHMENTTABLEMODEL_H__
-#define __ATTACHMENTTABLEMODEL_H__
-
-#include "Mime.h"
-
-class AttachmentTableModel : public QAbstractTableModel {
-Q_OBJECT
-
-public:
- explicit AttachmentTableModel(QObject *parent = nullptr);
-
- explicit AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent = nullptr);
-
- int rowCount(const QModelIndex &parent) const override;
-
- int columnCount(const QModelIndex &parent) const override;
-
- [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
-
- [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
-
- void add(const MimePart& mp);
-
- MimePart getSelectedMimePart(QModelIndex index);
-
- MimePart getMimePart(int index);
- //QList<MimePart> getSelectedMimeParts(QModelIndexList indexes);
-
-private:
- QList<MimePart> listOfMimeparts;
-};
-
-#endif // __ATTACHMENTTABLEMODEL_H__
diff --git a/include/ui/QuitDialog.h b/include/ui/QuitDialog.h
index 8d69cfd2..19af7534 100755
--- a/include/ui/QuitDialog.h
+++ b/include/ui/QuitDialog.h
@@ -1,22 +1,25 @@
-/*
- * keymgmt.h
+/**
+ * This file is part of GPGFrontend.
*
- * Copyright 2008 gpg4usb-team <[email protected]>
+ * GPGFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This file is part of gpg4usb.
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Gpg4usb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
*
- * Gpg4usb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
*
- * You should have received a copy of the GNU General Public License
- * along with gpg4usb. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef __QUITDIALOG_H__
@@ -30,7 +33,7 @@ Q_OBJECT
public:
QuitDialog(QWidget *parent, const QHash<int, QString>& unsavedDocs);
- bool isDiscarded() const;
+ [[nodiscard]] bool isDiscarded() const;
QList<int> getTabIdsToSave();
diff --git a/include/ui/SendMailDialog.h b/include/ui/SendMailDialog.h
new file mode 100644
index 00000000..e01802d3
--- /dev/null
+++ b/include/ui/SendMailDialog.h
@@ -0,0 +1,66 @@
+/**
+ * This file is part of GPGFrontend.
+ *
+ * GPGFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#ifndef GPGFRONTEND_SENDMAILDIALOG_H
+#define GPGFRONTEND_SENDMAILDIALOG_H
+
+#include "GpgFrontend.h"
+
+class SendMailDialog : public QDialog {
+Q_OBJECT
+public:
+ explicit SendMailDialog(QString text, QWidget *parent = nullptr);
+
+private slots:
+
+ void slotConfirm();
+
+private:
+
+ QString appPath;
+ QSettings settings;
+
+ QLineEdit *senderEdit;
+ QTextEdit *recipientEdit;
+ QLineEdit *subjectEdit;
+ QPushButton *confirmButton;
+
+ QLabel *errorLabel;
+ QString mText;
+
+ QString smtpAddress = settings.value("sendMail/smtpAddress", QString()).toString();
+ QString username = settings.value("sendMail/username", QString()).toString();
+ QString password = settings.value("sendMail/password", QString()).toString();
+ QString defaultSender = settings.value("sendMail/defaultSender", QString()).toString();
+ QString connectionTypeSettings = settings.value("sendMail/connectionType", QString()).toString();
+ int port = settings.value("sendMail/port", QString()).toInt();
+
+ QRegularExpression re_email{
+ R"((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]))"};
+
+ bool check_email_address(const QString &str);
+};
+
+
+#endif //GPGFRONTEND_SENDMAILDIALOG_H
diff --git a/include/ui/SettingsDialog.h b/include/ui/SettingsDialog.h
index f1a2863c..133a8ec7 100755
--- a/include/ui/SettingsDialog.h
+++ b/include/ui/SettingsDialog.h
@@ -66,24 +66,37 @@ signals:
};
-class MimeTab : public QWidget {
+class SendMailTab : public QWidget {
Q_OBJECT
public:
- explicit MimeTab(QWidget *parent = nullptr);
+ explicit SendMailTab(QWidget *parent = nullptr);
void setSettings();
void applySettings();
+private slots:
+
+ void slotCheckConnection();
+
+ void slotCheckBoxSetEnableDisable(int state);
+
private:
QString appPath;
QSettings settings;
- QCheckBox *mimeParseCheckBox;
- QCheckBox *mimeQPCheckBox;
- QCheckBox *mimeOpenAttachmentCheckBox;
+ QCheckBox *enableCheckBox;
+
+ QLineEdit *smtpAddress;
+ QLineEdit *username;
+ QLineEdit *password;
+ QSpinBox *portSpin;
+ QComboBox *connectionTypeComboBox;
+ QLineEdit *defaultSender;
+
+ QPushButton *checkConnectionButton;
signals:
@@ -115,6 +128,7 @@ private:
QRadioButton *iconTextButton;
QRadioButton *iconIconsButton;
QRadioButton *iconAllButton;
+ QSpinBox *infoBoardFontSizeSpin;
QCheckBox *windowSizeCheckBox;
signals:
@@ -208,7 +222,7 @@ public:
explicit SettingsDialog(GpgME::GpgContext *ctx, QWidget *parent = nullptr);
GeneralTab *generalTab;
- MimeTab *mimeTab;
+ SendMailTab *sendMailTab;
AppearanceTab *appearanceTab;
KeyserverTab *keyserverTab;
AdvancedTab *advancedTab;
diff --git a/include/ui/WaitingDialog.h b/include/ui/WaitingDialog.h
index 64c77ad9..df781073 100644
--- a/include/ui/WaitingDialog.h
+++ b/include/ui/WaitingDialog.h
@@ -28,7 +28,7 @@ class WaitingDialog : public QDialog {
Q_OBJECT
public:
- WaitingDialog(QWidget *parent = nullptr);
+ WaitingDialog(const QString &title, QWidget *parent);
public slots:
diff --git a/include/ui/AboutDialog.h b/include/ui/help/AboutDialog.h
index b7d54544..74391b5a 100644
--- a/include/ui/AboutDialog.h
+++ b/include/ui/help/AboutDialog.h
@@ -52,6 +52,29 @@ public:
};
/**
+ * @brief Class containing the main tab of about dialog
+ *
+ */
+class UpdateTab : public QWidget {
+Q_OBJECT
+
+ QLabel *currentVersionLabel;
+
+ QLabel *latestVersionLabel;
+
+ QLabel *upgradeLabel;
+
+ QProgressBar *pb;
+
+ QString currentVersion;
+
+public:
+ explicit UpdateTab(QWidget *parent = nullptr);
+
+ void getLatestVersion();
+};
+
+/**
* @brief Class for handling the about dialog
*
*/
@@ -59,7 +82,7 @@ class AboutDialog : public QDialog {
Q_OBJECT
public:
- explicit AboutDialog(QWidget *parent = nullptr);
+ explicit AboutDialog(int defaultIndex, QWidget *parent);
};
#endif // __ABOUTDIALOG_H__
diff --git a/include/ui/help/VersionCheckThread.h b/include/ui/help/VersionCheckThread.h
new file mode 100644
index 00000000..10c9da87
--- /dev/null
+++ b/include/ui/help/VersionCheckThread.h
@@ -0,0 +1,32 @@
+//
+// Created by Administrator on 2021/7/12.
+//
+
+#ifndef GPGFRONTEND_VERSIONCHECKTHREAD_H
+#define GPGFRONTEND_VERSIONCHECKTHREAD_H
+
+#include "GpgFrontend.h"
+
+class VersionCheckThread : public QThread {
+Q_OBJECT
+
+public:
+
+ VersionCheckThread(QNetworkReply *networkReply);
+
+signals:
+
+ void upgradeVersion(const QString &currentVersion, const QString &latestVersion);
+
+protected:
+
+ void run() override;
+
+private:
+
+ QNetworkReply* mNetworkReply;
+
+};
+
+
+#endif //GPGFRONTEND_VERSIONCHECKTHREAD_H
diff --git a/include/ui/keypair_details/KeyPairDetailTab.h b/include/ui/keypair_details/KeyPairDetailTab.h
index 6d041f97..bb364718 100644
--- a/include/ui/keypair_details/KeyPairDetailTab.h
+++ b/include/ui/keypair_details/KeyPairDetailTab.h
@@ -36,10 +36,10 @@ class KeyPairDetailTab : public QWidget {
Q_OBJECT
/**
- * @details Return QString with a space inserted at every fourth character
- *
- * @param fingerprint The fingerprint to be beautified
- */
+ * @details Return QString with a space inserted at every fourth character
+ *
+ * @param fingerprint The fingerprint to be beautified
+ */
static QString beautifyFingerprint(QString fingerprint);
void createKeyServerOperaMenu();
@@ -64,6 +64,8 @@ private slots:
void slotUpdateKeyToServer();
+ void slotGenRevokeCert();
+
private:
QString *keyid; /** The id of the key the details should be shown for */
diff --git a/include/ui/widgets/Attachments.h b/include/ui/widgets/Attachments.h
deleted file mode 100644
index 00433028..00000000
--- a/include/ui/widgets/Attachments.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-#ifndef __ATTACHMENTS_H__
-#define __ATTACHMENTS_H__
-
-#include "ui/AttachmentTableModel.h"
-
-class Attachments : public QWidget {
-Q_OBJECT
-
-public slots:
-
- void slotSaveFile();
-
- void slotOpenFile();
-
-public:
- explicit Attachments(QWidget *parent = nullptr);
-
- void addMimePart(MimePart *mp);
-
-private:
- void createActions();
-
- void saveByteArrayToFile(QByteArray outBuffer, QString filename);
-
- QAction *saveFileAct{};
- QAction *openFileAct{};
- AttachmentTableModel *table;
- QTableView *tableView;
- QSettings settings;
-
-protected:
- void contextMenuEvent(QContextMenuEvent *event) override;
-};
-
-#endif // __ATTACHMENTS_H__
diff --git a/include/ui/widgets/FilePage.h b/include/ui/widgets/FilePage.h
index 3d2c8e72..45d638fa 100644
--- a/include/ui/widgets/FilePage.h
+++ b/include/ui/widgets/FilePage.h
@@ -57,6 +57,10 @@ private slots:
void onCustomContextMenu(const QPoint &point);
+protected:
+
+ void keyPressEvent(QKeyEvent *event) override;
+
private:
@@ -64,6 +68,7 @@ private:
QTreeView *dirTreeView;
QLineEdit *pathEdit;
QString mPath;
+ QString selectedPath;
QPushButton *upLevelButton;
QPushButton *goPathButton;
diff --git a/include/ui/widgets/InfoBoardWidget.h b/include/ui/widgets/InfoBoardWidget.h
index f487b72c..2e5f9034 100644
--- a/include/ui/widgets/InfoBoardWidget.h
+++ b/include/ui/widgets/InfoBoardWidget.h
@@ -95,6 +95,10 @@ public slots:
void slotRefresh(const QString &text, InfoBoardStatus status);
private:
+
+ QString appPath;
+ QSettings settings;
+
QMenu *detailMenu; /** Menu for te Button in verfiyNotification */
QAction *importFromKeyserverAct; /** Action for importing keys from keyserver which are notin keylist */
QTextEdit *infoBoard;
diff --git a/include/ui/widgets/KeyList.h b/include/ui/widgets/KeyList.h
index 413d0969..231255b6 100644
--- a/include/ui/widgets/KeyList.h
+++ b/include/ui/widgets/KeyList.h
@@ -73,6 +73,8 @@ public:
void addMenuAction(QAction *act);
+ void addSeparator();
+
QStringList *getChecked();
void getCheckedKeys(QVector<GpgKey> &keys);
diff --git a/resource/gpgfrontend/usr/share/metainfo/pub.gpgfrontend.gpgfrontend.metainfo.xml b/resource/gpgfrontend/usr/share/metainfo/pub.gpgfrontend.gpgfrontend.metainfo.xml
new file mode 100644
index 00000000..49d409e5
--- /dev/null
+++ b/resource/gpgfrontend/usr/share/metainfo/pub.gpgfrontend.gpgfrontend.metainfo.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2013 First Lastname <[email protected]> -->
+<component type="desktop-application">
+ <id>pub.gpgfrontend.gpgfrontend</id>
+ <metadata_license>FSFAP</metadata_license>
+ <project_license>GPL-3.0+</project_license>
+ <name>GpgFrontend</name>
+ <summary>Take the initiative to protect privacy in your own hands</summary>
+
+ <description>
+ <p>
+ GpgFrontend is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.
+ </p>
+ <p>
+ By using GpgFrontend, you can quickly encrypt and decrypt text or files.
+ Or at the same time as the above operations, you can add your own signature
+ to let others know that this document or this paragraph of text was issued by you.
+ </p>
+ <p>For moew information visit https://gpgfrontend.pub/</p>
+
+ </description>
+
+ <launchable type="desktop-id">gpgfrontend.desktop</launchable>
+
+ <screenshots>
+ <screenshot type="default">
+ <caption>Main Window</caption>
+ <image>https://raw.githubusercontent.com/saturneric/Blob/master/screenshots/keygen_ubuntu.png</image>
+ </screenshot>
+ </screenshots>
+
+ <url type="homepage">https://gpgfrontend.pub/</url>
+ <project_group>GNOME</project_group>
+ <developer_name>Saturneric</developer_name>
+</component> \ No newline at end of file
diff --git a/resource/icons/refresh.png b/resource/icons/refresh.png
new file mode 100644
index 00000000..54745560
--- /dev/null
+++ b/resource/icons/refresh.png
Binary files differ
diff --git a/resource/icons/up.png b/resource/icons/up.png
new file mode 100644
index 00000000..46c47c70
--- /dev/null
+++ b/resource/icons/up.png
Binary files differ
diff --git a/resource/ts/gpgfrontend_en_us.ts b/resource/ts/gpgfrontend_en_us.ts
index c718def2..0042e061 100644
--- a/resource/ts/gpgfrontend_en_us.ts
+++ b/resource/ts/gpgfrontend_en_us.ts
@@ -4,30 +4,35 @@
<context>
<name>AboutDialog</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="29"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/>
<source>About </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="35"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/>
<source>General</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="36"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/>
<source>Translators</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/>
+ <source>Update</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>AdvancedTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="580"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="679"/>
<source>Show Steganography Options [Advanced]</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="582"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="681"/>
<source>Show Steganographic Options.</source>
<translation type="unfinished"></translation>
</message>
@@ -35,179 +40,159 @@
<context>
<name>AppearanceTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="368"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="444"/>
<source>Iconsize</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="370"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="446"/>
<source>small</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="371"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="447"/>
<source>medium</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="372"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="448"/>
<source>large</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="388"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="464"/>
<source>Iconstyle</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="390"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="466"/>
<source>just text</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="391"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="467"/>
<source>just icons</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="392"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="468"/>
<source>text and icons</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="484"/>
<source>Windowstate</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="411"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="487"/>
<source>Save window size and position on exit.</source>
<translation type="unfinished"></translation>
</message>
-</context>
-<context>
- <name>AttachmentTableModel</name>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/>
- <source>Filename</source>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="495"/>
+ <source>Information Board</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/>
- <source>Contenttype</source>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="501"/>
+ <source> Front Size</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
- <name>Attachments</name>
- <message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/>
- <source>Save File</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/>
- <source>Save this file</source>
- <translation type="unfinished"></translation>
- </message>
+ <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/>
- <source>Open File</source>
+ <location filename="../../src/ui/Wizard.cpp" line="165"/>
+ <source>Choose your action...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/>
- <source>Open this file</source>
+ <location filename="../../src/ui/Wizard.cpp" line="166"/>
+ <source>...by clicking on the appropriate link.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/>
- <source>File</source>
+ <location filename="../../src/ui/Wizard.cpp" line="168"/>
+ <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/>
- <source>Cannot write file %1:
-%2.</source>
+ <location filename="../../src/ui/Wizard.cpp" line="170"/>
+ <source>Generate Key</source>
<translation type="unfinished"></translation>
</message>
-</context>
-<context>
- <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="161"/>
- <source>Choose your action...</source>
+ <location filename="../../src/ui/Wizard.cpp" line="176"/>
+ <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="162"/>
- <source>...by clicking on the appropriate link.</source>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <source>Encrypt &amp; Decrypt Text</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="164"/>
- <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>or</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="172"/>
- <source>If you want to learn how to encrypt and decrypt text, you can read </source>
+ <location filename="../../src/ui/Wizard.cpp" line="180"/>
+ <source>Sign &amp; Verify Text</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="174"/>
- <location filename="../../src/ui/Wizard.cpp" line="183"/>
- <source>this document</source>
+ <location filename="../../src/ui/Wizard.cpp" line="188"/>
+ <source>If you want to operate file, you can read </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="181"/>
- <source>If you want to sign and verify text, you can read </source>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>Encrypt &amp; Sign File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="166"/>
- <source>create a new keypair</source>
+ <location filename="../../src/ui/Wizard.cpp" line="192"/>
+ <source>Sign &amp; Verify File</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ConclusionPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="397"/>
+ <location filename="../../src/ui/Wizard.cpp" line="407"/>
<source>Ready.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="398"/>
+ <location filename="../../src/ui/Wizard.cpp" line="408"/>
<source>Have fun with GPGFrontend!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="400"/>
+ <location filename="../../src/ui/Wizard.cpp" line="410"/>
<source>You are ready to use GPGFrontend now.&lt;br&gt;&lt;br&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="402"/>
+ <location filename="../../src/ui/Wizard.cpp" line="412"/>
<source>The Online Document</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="403"/>
+ <location filename="../../src/ui/Wizard.cpp" line="413"/>
<source> will get you started with GPGFrontend. It will open in the main window.&lt;br&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="410"/>
+ <location filename="../../src/ui/Wizard.cpp" line="420"/>
<source>Open offline help.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="413"/>
+ <location filename="../../src/ui/Wizard.cpp" line="423"/>
<source>Dont show the wizard again.</source>
<translation type="unfinished"></translation>
</message>
@@ -267,23 +252,45 @@
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
<source>Couldn&apos;t open file</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/>
+ <source>Error Occurred During Encryption</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/>
+ <source>Error Occurred During Decryption</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
+ <source>Error Occurred During Signature</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/>
<source>File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/>
<source>File exists! Do you want to overwrite it?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/>
<source>Cannot write file %1:
%2.</source>
<translation type="unfinished"></translation>
@@ -292,52 +299,52 @@
<context>
<name>FilePage</name>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/>
<source>Open</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/>
<source>Delete</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/>
<source>Encrypt and Sign</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/>
<source>Decrypt and Verify</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/>
<source>Only Sign</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/>
<source>Only Verify</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/>
<source>Warning</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/>
<source>Are you sure you want to delete it?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/>
<source>Unable to delete the file or folder.</source>
<translation type="unfinished"></translation>
</message>
@@ -353,57 +360,57 @@
<context>
<name>GeneralTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="135"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="137"/>
<source>Remember Password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="138"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="140"/>
<source>Remember password until closing gpg4usb</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="145"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="147"/>
<source>Save Checked Keys</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="148"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="150"/>
<source>Save checked private keys on exit and restore them on next start.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="157"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="159"/>
<source>Confirm drag&apos;n&apos;drop key import</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="162"/>
<source>Import files dropped on the keylist without confirmation.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="167"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="169"/>
<source>Language</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="176"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="178"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; GpgFrontend will restart automatically if you change the language!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="185"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="187"/>
<source>Own key</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="193"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="195"/>
<source>&lt;none&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="207"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="209"/>
<source>Key pair for synchronization and identity authentication</source>
<translation type="unfinished"></translation>
</message>
@@ -411,42 +418,32 @@
<context>
<name>GpgME::GpgContext</name>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="90"/>
- <source>ENV Loading Failed</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="91"/>
- <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="577"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="528"/>
<source>Wrong password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="585"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="536"/>
<source>Enter Password for</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="589"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="540"/>
<source>Enter Password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>Key Selection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>No Private Key Selected</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="804"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="746"/>
<source>Error in signing:</source>
<translation type="unfinished"></translation>
</message>
@@ -454,22 +451,22 @@
<context>
<name>GpgPathsTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="612"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="711"/>
<source>Relative path to keydb</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="625"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="724"/>
<source>Current keydb path: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="630"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="729"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; Gpg4usb will restart automatically if you change the keydb path!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="659"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="758"/>
<source>Choose keydb directory</source>
<translation type="unfinished"></translation>
</message>
@@ -477,32 +474,32 @@
<context>
<name>ImportFromGnupgPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="292"/>
+ <location filename="../../src/ui/Wizard.cpp" line="302"/>
<source>Import keys...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="293"/>
+ <location filename="../../src/ui/Wizard.cpp" line="303"/>
<source>...from existing GnuPG installation</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="295"/>
+ <location filename="../../src/ui/Wizard.cpp" line="305"/>
<source>You can import keys from a locally installed GnuPG.&lt;br&gt;&lt;br&gt; The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.&lt;br&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="299"/>
+ <location filename="../../src/ui/Wizard.cpp" line="309"/>
<source>Import keys from GnuPG</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Import Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Couldn&apos;t locate GnuPG home directory</source>
<translation type="unfinished"></translation>
</message>
@@ -510,47 +507,47 @@
<context>
<name>ImportFromGpg4usbPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="215"/>
+ <location filename="../../src/ui/Wizard.cpp" line="225"/>
<source>Import from...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="216"/>
+ <location filename="../../src/ui/Wizard.cpp" line="226"/>
<source>...existing GPGFrontend</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="218"/>
+ <location filename="../../src/ui/Wizard.cpp" line="228"/>
<source>You can import keys and/or settings from existing GPGFrontend. &lt;br&gt;&lt;br&gt;Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="225"/>
+ <location filename="../../src/ui/Wizard.cpp" line="235"/>
<source>Keys</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="229"/>
+ <location filename="../../src/ui/Wizard.cpp" line="239"/>
<source>Configuration</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="231"/>
+ <location filename="../../src/ui/Wizard.cpp" line="241"/>
<source>Import from GPGFrontend</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="246"/>
+ <location filename="../../src/ui/Wizard.cpp" line="256"/>
<source>Other GPGFrontend directory</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="265"/>
+ <location filename="../../src/ui/Wizard.cpp" line="275"/>
<source>Configuration Imported</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="266"/>
+ <location filename="../../src/ui/Wizard.cpp" line="276"/>
<source>Imported Configuration from old GPGFrontend.&lt;br&gt;Will now restart to activate the configuration.</source>
<translation type="unfinished"></translation>
</message>
@@ -558,30 +555,35 @@
<context>
<name>InfoBoardWidget</name>
<message>
- <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/>
<source>Import missing key from Keyserver</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/>
+ <source>Optional Actions Menu</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>InfoTab</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="55"/>
- <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, &lt;br&gt;cross-platform, and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/>
+ <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, cross-platform, &lt;br&gt;and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="63"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/>
<source>&lt;br&gt;&lt;br&gt; Built with Qt </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="64"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/>
<source> and GPGME </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="65"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/>
<source>&lt;br&gt;Built at </source>
<translation type="unfinished"></translation>
</message>
@@ -590,7 +592,7 @@
<name>IntroPage</name>
<message>
<location filename="../../src/ui/Wizard.cpp" line="111"/>
- <source>Getting started...</source>
+ <source>Getting Started...</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -600,11 +602,31 @@
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="114"/>
- <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.&lt;br&gt;&lt;br&gt;For more information have a look at the &lt;a href=&apos;docu_concepts.html&apos;&gt;concepts&lt;/a&gt; (by clicking the link, the page will open in the main window). &lt;br&gt;</source>
+ <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="116"/>
+ <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="117"/>
+ <source>For brief information have a look at the</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="118"/>
+ <source>Overview</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="123"/>
+ <location filename="../../src/ui/Wizard.cpp" line="119"/>
+ <source>by clicking the link, the page will open in the web browser</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="127"/>
<source>Choose a Language</source>
<translation type="unfinished"></translation>
</message>
@@ -652,17 +674,18 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/>
- <source> Expiration time no more than 2 years. </source>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/>
+ <source> Expiration time no more than 2 years.
+</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/>
<source>Generating Key...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/>
<source>Collecting random data for key generation.
This may take a while.
To speed up the process use your computer
@@ -670,87 +693,92 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/>
+ <source>Key Usage</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/>
<source>Encryption</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/>
<source>Signing</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/>
<source>Certification</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/>
<source>Authentication</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>Success</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>The new key pair has been generated.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>Failure</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>An error occurred during key generation.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/>
<source>Name:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
<source>Email Address:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
<source>Comment:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
<source>Expiration Date:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
<source>Never Expire</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
<source>KeySize (in Bit):</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
<source>Key Type:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
<source>Non Pass Phrase</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/>
<source>Basic Information</source>
<translation type="unfinished"></translation>
</message>
@@ -758,27 +786,27 @@
<context>
<name>KeyGenPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="356"/>
+ <location filename="../../src/ui/Wizard.cpp" line="366"/>
<source>Create a keypair...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="357"/>
+ <location filename="../../src/ui/Wizard.cpp" line="367"/>
<source>...for decrypting and signing messages</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="358"/>
+ <location filename="../../src/ui/Wizard.cpp" line="368"/>
<source>You should create a new keypair.The pair consists of a public and a private key.&lt;br&gt;Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.&lt;br&gt;For more information have a look at the offline tutorial (which then is shown in the main window):</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="365"/>
+ <location filename="../../src/ui/Wizard.cpp" line="375"/>
<source>Offline tutorial</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="372"/>
+ <location filename="../../src/ui/Wizard.cpp" line="382"/>
<source>Create New Key</source>
<translation type="unfinished"></translation>
</message>
@@ -941,23 +969,23 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
<source>Import Keys</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/>
<source>You&apos;ve dropped something on the table.
GpgFrontend will now try to import key(s).</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/>
<source>Always import without bothering.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/>
<source>Couldn&apos;t Open File: </source>
<translation type="unfinished"></translation>
</message>
@@ -966,7 +994,7 @@
<name>KeyMgmt</name>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="81"/>
- <source>KeyPairs Management</source>
+ <source>Key Pair Management</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1251,166 +1279,205 @@
<context>
<name>KeyPairDetailTab</name>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
<source>Owner</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
<source>Master Key</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/>
<source>Fingerprint</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/>
<source>Additional UIDs</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Exists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Not Exists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
<source>Name:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/>
<source>Email Address:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/>
<source>Comment:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
<source>Key ID: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
<source>Algorithm: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
<source>Key Size:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
<source>Nominal Usage: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
<source>Actual Usage: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
<source>Expires on: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/>
<source>Last Update: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/>
<source>Secret Key Existence: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
<source>Copy</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/>
<source>copy fingerprint to clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/>
<source>Operations</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/>
- <source>Export Private Key (Include Subkeys)</source>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/>
+ <source>Export Private Key (Include Subkey)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/>
+ <source>You are about to export your</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/>
+ <source>PRIVATE KEY</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/>
+ <source>This is NOT your Public Key, so DON&apos;T give it away.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/>
+ <source>Do you REALLY want to export your PRIVATE KEY?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/>
<source>Modify Expiration Datetime (Master Key)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/>
<source>Key Server Operation (Pubkey)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/>
- <source>Warning: The Master Key has expired.</source>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/>
+ <source>Generate Revoke Certificate</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/>
- <source>Warning: The Master Key has been revoked</source>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/>
+ <source>Warning: The Master Key has expired.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/>
- <source>Exporting private Key</source>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/>
+ <source>Warning: The Master Key has been revoked</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/>
- <source>&lt;h3&gt;You are about to export your &lt;font color=&quot;red&quot;&gt;PRIVATE KEY&lt;/font&gt;!&lt;/h3&gt;
-This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALLY want to export your PRIVATE KEY?</source>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/>
+ <source>Exporting private Key</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/>
<source>Export Key To File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/>
<source>Key Files</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Export Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Couldn&apos;t open %1 for writing</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/>
<source>Never Expire</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/>
- <source>Upload Key Pair</source>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/>
+ <source>Upload Key Pair to Key Server</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/>
<source>Update Key Pair</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/>
+ <source>Generate revocation certificate</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/>
+ <source>Revocation Certificates</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>KeyPairSubkeyTab</name>
@@ -1420,82 +1487,82 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
<source>Key ID: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
<source>Algorithm: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
<source>Key Size:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
<source>Usage: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
<source>Expires On </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
<source>Last Update: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
<source>Existence: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/>
<source>Fingerprint: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Subkey ID</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Key Size</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Algo</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Create Date</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Expire Date</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/>
<source>Never Expire</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/>
<source>Never Expires</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/>
<source>Edit Expire Date</source>
<translation type="unfinished"></translation>
</message>
@@ -1513,182 +1580,192 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/>
+ <source>UIDs</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/>
+ <source>Signature of Selected UID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Email</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Comment</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Key ID</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Create Date</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Expired Date</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/>
<source>Never Expires</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/>
<source>Invalid Operation</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/>
<source>Please select one or more UIDs before doing this operation.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/>
<source>Sign Selected UID(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/>
<source>Delete Selected UID(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/>
<source>Successful Operation</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
<source>Successfully added a new UID.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/>
<source>Operation Failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/>
<source>An error occurred during the operation.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/>
<source>Deleting UIDs</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/>
<source>Are you sure that you want to delete the following uids?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/>
<source>The action can not be undone.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/>
<source>Set Primary UID</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/>
<source>Are you sure that you want to set the Primary UID to?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/>
<source>Set As Primary</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/>
<source>Sign UID</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/>
<source>Delete UID</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/>
<source>Please select one UID before doing this operation.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/>
<source>Deleting UID</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/>
<source>Are you sure that you want to delete the following uid?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/>
<source>Delete(Revoke) Key Signature</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/>
<source>Please select one Key Signature before doing this operation.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/>
<source>To delete the signature, you need to have its corresponding public key in the local database.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/>
<source>Deleting Key Signature</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/>
<source>Are you sure that you want to delete the following signature?</source>
<translation type="unfinished"></translation>
</message>
@@ -1752,50 +1829,50 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/>
- <source>&lt;h4&gt;Text is empty.&lt;/h4&gt;</source>
+ <source>Text is empty.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/>
- <source>Not Key Found</source>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/>
+ <source>Too many responses from keyserver!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/>
- <source>Timeout</source>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/>
+ <source>No keys found, input may be kexId, retrying search with 0x.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/>
- <source>Key Server Not Found</source>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/>
+ <source>No keys found containing the search string!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/>
- <source>Connection Error</source>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/>
+ <source>Insufficiently specific search string!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/>
- <source>&lt;h4&gt;CToo many responses from keyserver!&lt;/h4&gt;</source>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/>
+ <source>Not Key Found</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/>
- <source>&lt;h4&gt;No keys found, input may be kexId, retrying search with 0x.&lt;/h4&gt;</source>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/>
+ <source>Timeout</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/>
- <source>&lt;h4&gt;No keys found containing the search string!&lt;/h4&gt;</source>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/>
+ <source>Key Server Not Found</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/>
- <source>&lt;h4&gt;Insufficiently specific search string!&lt;/h4&gt;</source>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/>
+ <source>Connection Error</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1893,27 +1970,27 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<context>
<name>KeyUploadDialog</name>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/>
<source>Uploading Public Key</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/>
<source>Key Not Found</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/>
<source>Timeout</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/>
<source>Key Server Not Found</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/>
<source>Connection Error</source>
<translation type="unfinished"></translation>
</message>
@@ -1921,12 +1998,12 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<context>
<name>KeyserverTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="508"/>
- <source>Default Keyserver for import:</source>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="607"/>
+ <source>Default Key Server for import:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="525"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="624"/>
<source>Add</source>
<translation type="unfinished"></translation>
</message>
@@ -1934,189 +2011,277 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<context>
<name>MainWindow</name>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/>
+ <location filename="../../src/MainWindow.cpp" line="35"/>
+ <source>Loading Gnupg</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="62"/>
+ <source>ENV Loading Failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="63"/>
+ <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/>
<source>No Key Selected</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/>
<source>Invalid Operation</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/>
<source>The selected key contains a key that does not actually have a encrypt usage.&lt;br/&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/>
+ <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/>
+ <source>Encrypting</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/>
+ <source>Function Disabled</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/>
+ <source>Please go to the settings interface to enable and configure this function.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/>
<source>The selected key contains a key that does not actually have a signature usage.&lt;br/&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/>
+ <source>Signing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/>
+ <source>Decrypting</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/>
+ <source>Verifying</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/>
<source>Invalid KeyPair</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/>
<source>The selected keypair cannot be used for signing and encryption at the same time.&lt;br/&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/>
<source>Incomplete Operation</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/>
<source>None of the selected key pairs can provide the encryption function.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/>
<source>None of the selected key pairs can provide the signature function.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/>
+ <source>Encrypting and Signing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/>
+ <source>Decrypting and Verifying</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <source>Select a file before doing it.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
<source>No permission to read this file.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
<source>No permission to create file.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/>
<source>Warning</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/>
<source>The target file already exists, do you need to overwrite it?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>An error occurred during operation.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/>
<source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
<source>No permission to read target file.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
<source>No permission to read signature file.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
<source>Select a file(.gpg/.asc) before doing it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/>
- <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/>
+ <source>Outdated Version</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
- <source>Select a file before doing it.</source>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/>
+ <source>This version(%1) is out of date, please update the latest version in time. </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/>
+ <source>You can download the latest version(%1) on Github Releases Page.&lt;br/&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/>
+ <source>Unreleased Version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/>
+ <source>This version(%1) has not been officially released and is not recommended for use in a production environment. &lt;br/&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/>
<source>There is one unencrypted file in attachment folder</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source>There are </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source> unencrypted files in attachment folder</source>
<translation type="unfinished"></translation>
</message>
@@ -2422,7 +2587,7 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/>
- <source>Manage &amp;keys</source>
+ <source>Manage &amp;Keys</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -2431,233 +2596,200 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/>
<source>Show the application&apos;s About box</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/>
+ <source>&amp;Check for Updates</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <source>Check for updates</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/>
<source>Open &amp;Wizard</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
<source>Open the wizard</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
<source>Append Selected Key(s) To Text</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
<source>Append The Selected Keys To Text in Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
- <source>Copy EMail-address</source>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <source>Copy Email</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/>
- <source>Copy selected EMailaddress to clipboard</source>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <source>Copy selected Email to clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
<source>Show Key Details</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/>
<source>Show Details for this Key</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/>
<source>Refresh Key From Key Server</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/>
<source>Refresh key from default key server</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/>
<source>Upload Public Key(s) To Server</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/>
<source>Upload The Selected Public Keys To Server</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/>
<source>Remove PGP Header</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/>
<source>Add PGP Header</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/>
<source>&amp;Edit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/>
<source>&amp;File...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/>
<source>&amp;Crypt</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
<source>&amp;Keys</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/>
<source>&amp;Import Key</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/>
<source>&amp;Steganography</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
<source>&amp;View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/>
<source>File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/>
<source>Crypt</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/>
<source>Key</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/>
<source>Edit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/>
<source>Special Edit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/>
<source>Import key from...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/>
<source>Import key</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/>
<source>Browser to view and operate file</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/>
<source>Browser</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/>
<source>Ready</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/>
<source>Key ToolBox</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/>
<source>Information Board</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/>
- <source>Attached files:</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>MimeTab</name>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
- <source>Decode quoted printable</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="292"/>
- <source>Try to recognize quoted printable.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="296"/>
- <source>Parse PGP/MIME (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="299"/>
- <source>Try to split attachments from PGP-MIME ecrypted messages.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="304"/>
- <source>Open with external application (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="306"/>
- <source>Open attachments with default application for the filetype.&lt;br&gt; There are at least two possible problems with this behaviour:&lt;ol&gt;&lt;li&gt;File needs to be saved unencrypted to attachments folder.&lt;br&gt; Its your job to clean this folder.&lt;/li&gt;&lt;li&gt;The external application may have its own temp files.&lt;/li&gt;&lt;/ol&gt;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
- <source>Enable opening with external applications.</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>QApplication</name>
@@ -2776,7 +2908,7 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="77"/>
- <source>&lt;h3&gt;%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?&lt;/h3&gt;</source>
+ <source>%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -2791,39 +2923,172 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
</message>
</context>
<context>
+ <name>SendMailDialog</name>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="35"/>
+ <source>Incomplete configuration</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="36"/>
+ <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="86"/>
+ <source> Recipient cannot be empty
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="91"/>
+ <source> One or more Recipient&apos;s Email Address is invalid
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="97"/>
+ <source> Sender cannot be empty
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="99"/>
+ <source> Sender&apos;s Email Address is invalid
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <source>Fail to Login into SMTP Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail to Send Mail to SMTP Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Success</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Succeed in Sending Mail to SMTP Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SendMailTab</name>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
+ <source>Enable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="311"/>
+ <source>SMTP Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="313"/>
+ <source>Username</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
+ <source>Password</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="317"/>
+ <source>Port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="319"/>
+ <source>Connection Security</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="322"/>
+ <source>Default Sender</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail to Login</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Success</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Succeed in connecting and login</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>SettingsDialog</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="38"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
<source>General</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="39"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
<source>Appearance</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
- <source>PGP/Mime</source>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="42"/>
+ <source>Send Mail</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
<source>Key Server</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="45"/>
<source>Advanced</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="56"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="58"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="101"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="103"/>
<source>System Default</source>
<translation type="unfinished"></translation>
</message>
@@ -2922,63 +3187,97 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<context>
<name>TextEdit</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/>
<source>untitled</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/>
<source>Warning</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/>
+ <source>Cannot read file %1:
+%2.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/>
<source>Open file</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/>
+ <source>File</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/>
+ <source>Cannot write file %1:
+%2.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
<source>Save file</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/>
+ <source>Unsaved document</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/>
+ <source>The document &quot;%1&quot; has been modified. Do you want to save your changes?&lt;br/&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/>
+ <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/>
<source>Application</source>
<translation type="unfinished"></translation>
</message>
+</context>
+<context>
+ <name>UpdateTab</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/>
- <source>Cannot read file %1:
-%2.</source>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/>
+ <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/>
- <source>File</source>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/>
+ <source>New versions not only represent new features, but also often represent functional and security fixes.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/>
- <source>Cannot write file %1:
-%2.</source>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/>
+ <source>Current Version: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/>
- <source>Unsaved document</source>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/>
+ <source>The current version is inconsistent with the latest version on github.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/>
- <source>&lt;h3&gt;The document &quot;%1&quot; has been modified.&lt;br/&gt;Do you want to save your changes?&lt;/h3&gt;</source>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/>
+ <source>Please click &lt;a href=&quot;https://github.com/saturneric/GpgFrontend/releases&quot;&gt;here&lt;/a&gt; to download the latest version.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
- <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/>
+ <source>Latest Version From Github: </source>
<translation type="unfinished"></translation>
</message>
</context>
diff --git a/resource/ts/gpgfrontend_zh_cht.ts b/resource/ts/gpgfrontend_es.ts
index 7bf4bd62..a3f8dd53 100644
--- a/resource/ts/gpgfrontend_zh_cht.ts
+++ b/resource/ts/gpgfrontend_es.ts
@@ -1,215 +1,198 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="zh_CN">
+<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="es_ES">
<context>
<name>AboutDialog</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="29"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/>
<source>About </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Acerca de</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="35"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/>
<source>General</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">General</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="36"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/>
<source>Translators</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/>
+ <source>Update</source>
+ <translation type="finished">Actualizar</translation>
</message>
</context>
<context>
<name>AdvancedTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="580"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="679"/>
<source>Show Steganography Options [Advanced]</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Mostrar opciones de steganography [Avanzado]</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="582"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="681"/>
<source>Show Steganographic Options.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Mostrar opciones de STANGANOGRÁFICA.</translation>
</message>
</context>
<context>
<name>AppearanceTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="368"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="444"/>
<source>Iconsize</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tamaño de ícono.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="370"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="446"/>
<source>small</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="371"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="447"/>
<source>medium</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">medio</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="372"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="448"/>
<source>large</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">grande</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="388"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="464"/>
<source>Iconstyle</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">IconStyle</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="390"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="466"/>
<source>just text</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Solo texto</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="391"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="467"/>
<source>just icons</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">solo iconos</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="392"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="468"/>
<source>text and icons</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Texto e Iconos</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="484"/>
<source>Windowstate</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado de ventanas</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="411"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="487"/>
<source>Save window size and position on exit.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Guardar el tamaño de la ventana y la posición en la salida.</translation>
</message>
-</context>
-<context>
- <name>AttachmentTableModel</name>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/>
- <source>Filename</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="495"/>
+ <source>Information Board</source>
+ <translation type="finished">Tarjeta de la información</translation>
</message>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/>
- <source>Contenttype</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="501"/>
+ <source> Front Size</source>
+ <translation type="finished">Tamaño delantero</translation>
</message>
</context>
<context>
- <name>Attachments</name>
+ <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/>
- <source>Save File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="165"/>
+ <source>Choose your action...</source>
+ <translation type="finished">Elige tu acción ...</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/>
- <source>Save this file</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="166"/>
+ <source>...by clicking on the appropriate link.</source>
+ <translation type="finished">... haciendo clic en el enlace apropiado.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/>
- <source>Open File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="168"/>
+ <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source>
+ <translation type="finished">Si nunca ha usado GPGFRontend antes y tampoco tiene una clave GPG, pero posiblemente quiera leer cómo leer</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/>
- <source>Open this file</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="170"/>
+ <source>Generate Key</source>
+ <translation type="finished">Generar clave</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/>
- <source>File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="176"/>
+ <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source>
+ <translation type="finished">Si desea aprender cómo cifrar, descifrar, firmar y verificar el texto, puede leer</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/>
- <source>Cannot write file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <source>Encrypt &amp; Decrypt Text</source>
+ <translation type="finished">Cifrar y descifrar texto</translation>
</message>
-</context>
-<context>
- <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="161"/>
- <source>Choose your action...</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>or</source>
+ <translation type="finished">o</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="162"/>
- <source>...by clicking on the appropriate link.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="180"/>
+ <source>Sign &amp; Verify Text</source>
+ <translation type="finished">Firmar y verificar el texto</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="164"/>
- <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="188"/>
+ <source>If you want to operate file, you can read </source>
+ <translation type="finished">Si desea operar el archivo, puede leer</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="172"/>
- <source>If you want to learn how to encrypt and decrypt text, you can read </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>Encrypt &amp; Sign File</source>
+ <translation type="finished">Cifrar y firmar archivo</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="174"/>
- <location filename="../../src/ui/Wizard.cpp" line="183"/>
- <source>this document</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/Wizard.cpp" line="181"/>
- <source>If you want to sign and verify text, you can read </source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/Wizard.cpp" line="166"/>
- <source>create a new keypair</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="192"/>
+ <source>Sign &amp; Verify File</source>
+ <translation type="finished">Firmar y verificar el archivo</translation>
</message>
</context>
<context>
<name>ConclusionPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="397"/>
+ <location filename="../../src/ui/Wizard.cpp" line="407"/>
<source>Ready.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Listo.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="398"/>
+ <location filename="../../src/ui/Wizard.cpp" line="408"/>
<source>Have fun with GPGFrontend!</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">¡Diviértete con GPGFRontend!</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="400"/>
+ <location filename="../../src/ui/Wizard.cpp" line="410"/>
<source>You are ready to use GPGFrontend now.&lt;br&gt;&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estás listo para usar GPGFRontend ahora. &lt;br&gt; &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="402"/>
+ <location filename="../../src/ui/Wizard.cpp" line="412"/>
<source>The Online Document</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">El documento en línea</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="403"/>
+ <location filename="../../src/ui/Wizard.cpp" line="413"/>
<source> will get you started with GPGFrontend. It will open in the main window.&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Te harás comenzar con GPGFRontend.Se abrirá en la ventana principal. &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="410"/>
+ <location filename="../../src/ui/Wizard.cpp" line="420"/>
<source>Open offline help.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ayuda fuera de línea abierta.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="413"/>
+ <location filename="../../src/ui/Wizard.cpp" line="423"/>
<source>Dont show the wizard again.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No vuelvas a mostrar al asistente.</translation>
</message>
</context>
<context>
@@ -217,129 +200,152 @@
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="32"/>
<source>Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo de descifrado</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="34"/>
<source>Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cifrar archivo</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="36"/>
<source>Sign File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo de firma</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="38"/>
<source>Verify File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Verificar archivo</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="47"/>
<source>Input Parameters</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Parámetros de entrada</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="53"/>
<source>Target File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo de destino</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="59"/>
<source>Output File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo de salida</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="75"/>
<source>Signature File(.sig) Path</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ruta del archivo de firma (.sig)</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="134"/>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="177"/>
<source>Open File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abrir documento</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="165"/>
<source>Save File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Guardar el archivo</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/>
- <source>Couldn&apos;t open file</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
+ <source>Couldn't open file</source>
+ <translation type="finished">No se pudo abrir el archivo</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/>
+ <source>Error</source>
+ <translation type="finished">Error</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/>
+ <source>Error Occurred During Encryption</source>
+ <translation type="finished">Se produjo un error durante el cifrado</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/>
+ <source>Error Occurred During Decryption</source>
+ <translation type="finished">Se produjo un error durante la descifrado.</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
+ <source>Error Occurred During Signature</source>
+ <translation type="finished">Se produjo un error durante la firma</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/>
<source>File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo</translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/>
<source>File exists! Do you want to overwrite it?</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">¡El archivo existe! ¿Quieres sobreescribirlo?</translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/>
<source>Cannot write file %1:
%2.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No se puede escribir archivo% 1:
+% 2.</translation>
</message>
</context>
<context>
<name>FilePage</name>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/>
<source>Open</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abierto</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/>
<source>Delete</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Borrar</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/>
<source>Encrypt and Sign</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cifrar y firmar</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/>
<source>Decrypt and Verify</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Descifrar y verificar</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/>
<source>Only Sign</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Solo signo</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/>
<source>Only Verify</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Solo verificar</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Advertencia</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/>
<source>Are you sure you want to delete it?</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">¿Estás seguro de que quieres borrarlo?</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/>
<source>Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/>
<source>Unable to delete the file or folder.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No se puede eliminar el archivo o la carpeta.</translation>
</message>
</context>
<context>
@@ -347,266 +353,281 @@
<message>
<location filename="../../src/ui/FindWidget.cpp" line="38"/>
<source>Find:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Encontrar:</translation>
</message>
</context>
<context>
<name>GeneralTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="135"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="137"/>
<source>Remember Password</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Recordar contraseña</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="138"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="140"/>
<source>Remember password until closing gpg4usb</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Recuerde la contraseña hasta que cierre GPG4USB</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="145"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="147"/>
<source>Save Checked Keys</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Guardar las llaves revisadas</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="148"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="150"/>
<source>Save checked private keys on exit and restore them on next start.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Guarda las llaves privadas revisadas en la salida y restaurándolas en el próximo inicio.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="157"/>
- <source>Confirm drag&apos;n&apos;drop key import</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="159"/>
+ <source>Confirm drag'n'drop key import</source>
+ <translation type="finished">Confirmar la tecla Drag'n'n'Drop Import</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="162"/>
<source>Import files dropped on the keylist without confirmation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar archivos cayeron en el keylist sin confirmación.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="167"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="169"/>
<source>Language</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Idioma</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="176"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="178"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; GpgFrontend will restart automatically if you change the language!</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&lt;B&gt; Nota: &lt;/ b&gt; GPGFRontend se reiniciará automáticamente si cambia el idioma!</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="185"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="187"/>
<source>Own key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="193"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="195"/>
<source>&lt;none&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&lt;ninguno&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="207"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="209"/>
<source>Key pair for synchronization and identity authentication</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Pareja de llaves para la autenticación de sincronización e identidad</translation>
</message>
</context>
<context>
<name>GpgME::GpgContext</name>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="90"/>
- <source>ENV Loading Failed</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="91"/>
- <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="577"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="528"/>
<source>Wrong password</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Contraseña incorrecta</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="585"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="536"/>
<source>Enter Password for</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ingrese la contraseña para</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="589"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="540"/>
<source>Enter Password</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Introducir la contraseña</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>Key Selection</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Selección de claves</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>No Private Key Selected</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No hay llave privada seleccionada</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="804"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="746"/>
<source>Error in signing:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error en la firma:</translation>
</message>
</context>
<context>
<name>GpgPathsTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="612"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="711"/>
<source>Relative path to keydb</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Camino relativo a KeyDB</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="625"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="724"/>
<source>Current keydb path: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ruta de KeyDB actual:</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="630"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="729"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; Gpg4usb will restart automatically if you change the keydb path!</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&lt;B&gt; Nota: &lt;/ b&gt; gpg4usb se reiniciará automáticamente si cambia la ruta KeyDB!</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="659"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="758"/>
<source>Choose keydb directory</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Elija el directorio de KeyDB</translation>
</message>
</context>
<context>
<name>ImportFromGnupgPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="292"/>
+ <location filename="../../src/ui/Wizard.cpp" line="302"/>
<source>Import keys...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar teclas ...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="293"/>
+ <location filename="../../src/ui/Wizard.cpp" line="303"/>
<source>...from existing GnuPG installation</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">... de la instalación de GNUPG existente</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="295"/>
+ <location filename="../../src/ui/Wizard.cpp" line="305"/>
<source>You can import keys from a locally installed GnuPG.&lt;br&gt;&lt;br&gt; The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Puede importar claves desde un GNUPG instalado localmente. &lt;br&gt; &lt;br&gt; La ubicación se lee desde el registro en Windows o se supone que es la carpeta .GNUPG en el directorio de su casa en Linux. &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="299"/>
+ <location filename="../../src/ui/Wizard.cpp" line="309"/>
<source>Import keys from GnuPG</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar claves de gnupg</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Import Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error de importación</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
- <source>Couldn&apos;t locate GnuPG home directory</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
+ <source>Couldn't locate GnuPG home directory</source>
+ <translation type="finished">No se pudo localizar el directorio de inicio de gnupg</translation>
</message>
</context>
<context>
<name>ImportFromGpg4usbPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="215"/>
+ <location filename="../../src/ui/Wizard.cpp" line="225"/>
<source>Import from...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar de...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="216"/>
+ <location filename="../../src/ui/Wizard.cpp" line="226"/>
<source>...existing GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">... gpgfrontend existente</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="218"/>
+ <location filename="../../src/ui/Wizard.cpp" line="228"/>
<source>You can import keys and/or settings from existing GPGFrontend. &lt;br&gt;&lt;br&gt;Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Puede importar claves y / o configuraciones desde GPGFrontend existente.&lt;br&gt; &lt;br&gt; Simplemente compruebe lo que desea importar, haga clic en el botón Importar y elija el directorio de su otro GPGFrontend en el cuadro de diálogo de archivo de apariencia.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="225"/>
+ <location filename="../../src/ui/Wizard.cpp" line="235"/>
<source>Keys</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Llaves</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="229"/>
+ <location filename="../../src/ui/Wizard.cpp" line="239"/>
<source>Configuration</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Configuración</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="231"/>
+ <location filename="../../src/ui/Wizard.cpp" line="241"/>
<source>Import from GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importación de GPGFRontend</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="246"/>
+ <location filename="../../src/ui/Wizard.cpp" line="256"/>
<source>Other GPGFrontend directory</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Otro GPGFrontend Directorio</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="265"/>
+ <location filename="../../src/ui/Wizard.cpp" line="275"/>
<source>Configuration Imported</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Configuración importada</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="266"/>
+ <location filename="../../src/ui/Wizard.cpp" line="276"/>
<source>Imported Configuration from old GPGFrontend.&lt;br&gt;Will now restart to activate the configuration.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Configuración importada desde el antiguo GPGFrontend. Se reiniciará ahora para activar la configuración.</translation>
</message>
</context>
<context>
<name>InfoBoardWidget</name>
<message>
- <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/>
<source>Import missing key from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar la tecla faltante de Keyserver</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/>
+ <source>Optional Actions Menu</source>
+ <translation type="finished">MENÚ DE ACCIONES OPCIONALES</translation>
</message>
</context>
<context>
<name>InfoTab</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="55"/>
- <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, &lt;br&gt;cross-platform, and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/>
+ <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, cross-platform, &lt;br&gt;and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It's licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
+ <translation type="finished">&lt;br&gt; &lt;Centre&gt; GPGFRontend es una herramienta de front-end de GPG de fácil uso, compacta, compacta, compacta y sin instalación. &lt;br&gt; Se visualiza la mayoría de las operaciones comunes de los comandos GPG. &lt;BR&gt; Está licenciado bajo el GPL V3 &lt;br&gt; &lt;br&gt; &lt;B&gt; Desarrollador: &lt;/ b&gt; &lt;br&gt; Saturnérico &lt;br&gt; &lt;br&gt; Si tiene alguna pregunta o sugerencia, plantee un problema &lt;br/&gt; a &lt;Ahref = &quot;https://github.com/saturnic/gpgfrontend&quot;&gt; github &lt;/a&gt; o envíe un correo a mi lista de correo en &lt;a href=&quot;mailto [email protected]&quot;&gt; [email protected] &lt;/ a&gt;.</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="63"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/>
<source>&lt;br&gt;&lt;br&gt; Built with Qt </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&lt;br&gt; &lt;br&gt; construido con qt</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="64"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/>
<source> and GPGME </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">y gpgme</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="65"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/>
<source>&lt;br&gt;Built at </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&lt;br&gt; construido en</translation>
</message>
</context>
<context>
<name>IntroPage</name>
<message>
<location filename="../../src/ui/Wizard.cpp" line="111"/>
- <source>Getting started...</source>
- <translation type="unfinished"></translation>
+ <source>Getting Started...</source>
+ <translation type="finished">Empezando...</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="112"/>
<source>... with GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">... con gpgfrontend</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="114"/>
- <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.&lt;br&gt;&lt;br&gt;For more information have a look at the &lt;a href=&apos;docu_concepts.html&apos;&gt;concepts&lt;/a&gt; (by clicking the link, the page will open in the main window). &lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source>
+ <translation type="finished">¡Bienvenido a usar GPGFRontend para descifrar y firmar texto o archivo!</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="123"/>
+ <location filename="../../src/ui/Wizard.cpp" line="116"/>
+ <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source>
+ <translation type="finished">Es una herramienta CRYPTO OpenPGP Potente, fácil de usar, compacta, multiplataforma y sin instalación.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="117"/>
+ <source>For brief information have a look at the</source>
+ <translation type="finished">Para obtener información breve, eche un vistazo a la</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="118"/>
+ <source>Overview</source>
+ <translation type="finished">Descripción general</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="119"/>
+ <source>by clicking the link, the page will open in the web browser</source>
+ <translation type="finished">Al hacer clic en el enlace, la página se abrirá en el navegador web.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="127"/>
<source>Choose a Language</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Elegir un idioma</translation>
</message>
</context>
<context>
@@ -614,22 +635,22 @@
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="31"/>
<source>KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Par de claves</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="32"/>
<source>UIDs</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Uids</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="33"/>
<source>Subkeys</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Subcecheras</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="40"/>
<source>Key Details</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Detalles clave</translation>
</message>
</context>
<context>
@@ -637,150 +658,159 @@
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="32"/>
<source>Generate Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generar clave</translation>
</message>
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="68"/>
<source> Name must contain at least five characters.
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">El nombre debe contener al menos cinco caracteres.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="70"/>
<source> Please give a email address.
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Por favor, proporcione una dirección de correo electrónico.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/>
- <source> Expiration time no more than 2 years. </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/>
+ <source> Expiration time no more than 2 years.
+</source>
+ <translation type="finished">Tiempo de vencimiento No más de 2 años.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/>
<source>Generating Key...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generando llave ...</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/>
<source>Collecting random data for key generation.
This may take a while.
To speed up the process use your computer
(e.g. browse the net, listen to music,...)</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Recogiendo datos aleatorios para la generación de claves.
+ Esto puede tardar un rato.
+ Para acelerar el proceso, use su computadora.
+ (Por ejemplo, navega por la red, escucha música, ...)</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/>
+ <source>Key Usage</source>
+ <translation type="finished">Uso clave</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/>
<source>Encryption</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/>
<source>Signing</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Firma</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/>
<source>Certification</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Certificación</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/>
<source>Authentication</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Autenticación</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>Success</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Éxito</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>The new key pair has been generated.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Se ha generado el nuevo par de llaves.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>Failure</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Falla</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>An error occurred during key generation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Se produjo un error durante la generación de claves.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/>
<source>Name:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nombre:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
<source>Email Address:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Dirección de correo electrónico:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
<source>Comment:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Comentario:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
<source>Expiration Date:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Fecha de caducidad:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nunca expira</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
<source>KeySize (in Bit):</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Keysize (en bit):</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
<source>Key Type:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tipo de llave:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
<source>Non Pass Phrase</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Frase sin paso</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/>
<source>Basic Information</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Información básica</translation>
</message>
</context>
<context>
<name>KeyGenPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="356"/>
+ <location filename="../../src/ui/Wizard.cpp" line="366"/>
<source>Create a keypair...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Crea un keypair ...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="357"/>
+ <location filename="../../src/ui/Wizard.cpp" line="367"/>
<source>...for decrypting and signing messages</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">... para descifrar y firmar mensajes</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="358"/>
+ <location filename="../../src/ui/Wizard.cpp" line="368"/>
<source>You should create a new keypair.The pair consists of a public and a private key.&lt;br&gt;Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.&lt;br&gt;For more information have a look at the offline tutorial (which then is shown in the main window):</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Debe crear un nuevo teclado. El par consiste en una clave pública y privada. Otros usuarios pueden usar la clave pública para cifrar mensajes para usted y verificar los mensajes firmados por usted. Puede usar la clave privada para descifrar y firmarMensajes. Para más información, eche un vistazo al tutorial fuera de línea (que luego se muestra en la ventana principal):</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="365"/>
+ <location filename="../../src/ui/Wizard.cpp" line="375"/>
<source>Offline tutorial</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tutorial fuera de línea</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="372"/>
+ <location filename="../../src/ui/Wizard.cpp" line="382"/>
<source>Create New Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Crear nueva llave</translation>
</message>
</context>
<context>
@@ -789,118 +819,118 @@
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="53"/>
<source>Key Update Details</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Detalles de actualización clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/>
<source>No keys found</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No se han encontrado llaves</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="55"/>
<source>Key Import Details</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Detalles de importación clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/>
<source>No keys found to import</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No se han encontrado llaves para importar</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="64"/>
<source>General key info</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Información general de clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="67"/>
<source>Considered:</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="71"/>
<source>Public unchanged:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Público sin cambios:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="76"/>
<source>Imported:</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="81"/>
<source>Not imported:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No importado:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="86"/>
<source>Private read:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">LEER PRIVADO:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="91"/>
<source>Private imported:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importado privado:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="96"/>
<source>Private unchanged:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Privado sin cambios:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nombre</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Correo electrónico</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Status</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Fingerprint</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Huella dactilar</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="135"/>
<source>private</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="138"/>
<source>public</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="141"/>
<source>unchanged</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">sin alterar</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="144"/>
<source>new key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">nueva llave</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="147"/>
<source>new subkey</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nueva Subkey</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="151"/>
<source>new signature</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">nueva firma</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="155"/>
<source>new uid</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nuevo uid</translation>
</message>
</context>
<context>
@@ -908,309 +938,310 @@
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Select</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Seleccione</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Type</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tipo</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nombre</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Email Address</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Dirección de correo electrónico</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Usage</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Uso</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Validity</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Validez</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Finger Print</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Huella dactilar</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
<source>Import Keys</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Teclas de importación</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/>
- <source>You&apos;ve dropped something on the table.
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/>
+ <source>You've dropped something on the table.
GpgFrontend will now try to import key(s).</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Has dejado caer algo sobre la mesa.
+ GPGFRontend ahora intentará importar la (s) clave (s).</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/>
<source>Always import without bothering.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Siempre importar sin molestarse.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/>
- <source>Couldn&apos;t Open File: </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/>
+ <source>Couldn't Open File: </source>
+ <translation type="finished">No se pudo abrir el archivo:</translation>
</message>
</context>
<context>
<name>KeyMgmt</name>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="81"/>
- <source>KeyPairs Management</source>
- <translation type="unfinished"></translation>
+ <source>Key Pair Management</source>
+ <translation type="finished">Gestión de pares clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="88"/>
<source>&amp;Open</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Abierto</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="89"/>
<source>Ctrl+O</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ctrl + o</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="90"/>
<source>Open Key File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abrir archivo de clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="93"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Cerca</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="94"/>
<source>Ctrl+Q</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ctrl + Q</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="96"/>
<source>Close</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cerca</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="99"/>
<source>New Keypair</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nuevo llave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="100"/>
<source>Ctrl+N</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ctrl + n</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="102"/>
<source>Generate KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generar par de claves</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="105"/>
<source>New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nueva Subkey</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="106"/>
<source>Ctrl+Shift+N</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">CTRL + MAYÚS + N</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="108"/>
<source>Generate Subkey For Selected KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generar subclave para la tecla seleccionada.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="111"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="152"/>
<source>&amp;File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Archivo</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="113"/>
<source>Import New Key From File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar nueva llave desde el archivo</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="116"/>
<source>&amp;Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Portapapeles</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="118"/>
<source>Import New Key From Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar nueva llave desde el portapapeles</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="121"/>
<source>&amp;Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp; Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="123"/>
<source>Import New Key From Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar nueva llave de Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="126"/>
<source>Export To &amp;Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Exportar al portapapeles</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="128"/>
<source>Export Selected Key(s) To Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Exportar la (s) clave (s) seleccionada (s) al portapapeles</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="131"/>
<source>Export To &amp;File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Exportar a &amp; Archivo</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="133"/>
<source>Export Selected Key(s) To File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Exportar clave seleccionada (s) para archivar</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="136"/>
<source>Delete Selected Key(s)</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar la (s) clave seleccionada (s)</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="137"/>
<source>Delete the Selected keys</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar las teclas seleccionadas</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="140"/>
<source>Delete Checked Key(s)</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar la (s) clave de verificación (s)</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="141"/>
<source>Delete the Checked keys</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar las teclas marcadas</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="145"/>
<source>Show Key Details</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Mostrar detalles clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="146"/>
<source>Show Details for this Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Mostrar detalles para esta clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="156"/>
<source>&amp;Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="157"/>
<source>&amp;Generate Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generar clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="161"/>
<source>&amp;Import Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">E importar clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="173"/>
<source>Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="181"/>
<source>Generate</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generar</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="182"/>
<source>Generate A New Keypair or Subkey</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generar un nuevo teclado o suba.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="191"/>
<source>Import key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tecla de importación</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="192"/>
<source>Import Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tecla de importación</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<source>Open Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Llave abierta</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="299"/>
<source>Key Files</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivos clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<source>Keyring files</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivos de llavero</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="218"/>
- <source>Couldn&apos;t Open File: </source>
- <translation type="unfinished"></translation>
+ <source>Couldn't Open File: </source>
+ <translation type="finished">No se pudo abrir el archivo:</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="268"/>
<source>Deleting Keys</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar llaves</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="269"/>
<source>Are you sure that you want to delete the following keys?</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">¿Está seguro de que desea eliminar las siguientes teclas?</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="270"/>
<source>The action can not be undone.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">La acción no se puede deshacer.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="299"/>
<source>Export Key To File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave de exportación a archivo</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="309"/>
<source>key(s) exported</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">llave (s) exportada</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="338"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="345"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación inválida</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="339"/>
<source>Please select one KeyPair before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Por favor seleccione una tecla antes de hacer esta operación.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="346"/>
<source>If a key pair does not have a private key then it will not be able to generate sub-keys.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Si un par de claves no tiene una clave privada, no podrá generar sub-llaves.</translation>
</message>
</context>
<context>
@@ -1218,198 +1249,237 @@
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="40"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nombre</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="41"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Correo electrónico</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="42"/>
<source>Comment</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Comentario</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="55"/>
<source>Create New UID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Crear nuevo uid</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="68"/>
<source> Name must contain at least five characters.
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">El nombre debe contener al menos cinco caracteres.</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="70"/>
<source> Please give a email address.
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Por favor, proporcione una dirección de correo electrónico.</translation>
</message>
</context>
<context>
<name>KeyPairDetailTab</name>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
<source>Owner</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
<source>Master Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Llave maestra</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/>
<source>Fingerprint</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Huella dactilar</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/>
<source>Additional UIDs</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">UIDS adicionales</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Exists</source>
+ <translation type="finished">Existe</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Not Exists</source>
+ <translation type="finished">No existe</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
<source>Name:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nombre:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/>
<source>Email Address:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Dirección de correo electrónico:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/>
<source>Comment:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Comentario:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
<source>Key ID: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">ID clave:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
<source>Algorithm: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Algoritmo:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
<source>Key Size:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tamaño de la llave:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
<source>Nominal Usage: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Uso nominal:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
<source>Actual Usage: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Uso actual:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
<source>Expires on: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Expira el:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/>
<source>Last Update: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Última actualización:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/>
<source>Secret Key Existence: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Existencia clave secreta:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
<source>Copy</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Dupdo</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/>
<source>copy fingerprint to clipboard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Copia la huella digital al portapapeles</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/>
<source>Operations</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operaciones</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/>
- <source>Export Private Key (Include Subkeys)</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/>
+ <source>Export Private Key (Include Subkey)</source>
+ <translation type="finished">Clave privada de exportación (incluir subclave)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/>
<source>Modify Expiration Datetime (Master Key)</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Modificar fecha de vencimiento (clave maestra)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/>
<source>Key Server Operation (Pubkey)</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación del servidor clave (Pubkey)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/>
+ <source>Generate Revoke Certificate</source>
+ <translation type="finished">Genera revocar certificado</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/>
<source>Warning: The Master Key has expired.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Advertencia: la clave maestra ha caducado.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/>
<source>Warning: The Master Key has been revoked</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Advertencia: la clave maestra ha sido revocada</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/>
<source>Exporting private Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Exportación de clave privada</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/>
+ <source>You are about to export your</source>
+ <translation type="finished">Estás a punto de exportar tu</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/>
+ <source>PRIVATE KEY</source>
+ <translation type="finished">LLAVE PRIVADA</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/>
+ <source>This is NOT your Public Key, so DON'T give it away.</source>
+ <translation type="finished">Esta no es su clave pública, así que no lo desye.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/>
- <source>&lt;h3&gt;You are about to export your &lt;font color=&quot;red&quot;&gt;PRIVATE KEY&lt;/font&gt;!&lt;/h3&gt;
-This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALLY want to export your PRIVATE KEY?</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/>
+ <source>Do you REALLY want to export your PRIVATE KEY?</source>
+ <translation type="finished">¿Realmente quieres exportar tu clave privada?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/>
<source>Export Key To File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave de exportación a archivo</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/>
<source>Key Files</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivos clave</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Export Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error de exportación</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
- <source>Couldn&apos;t open %1 for writing</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
+ <source>Couldn't open %1 for writing</source>
+ <translation type="finished">No se pudo abrir% 1 por escrito.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nunca expira</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/>
- <source>Upload Key Pair</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/>
+ <source>Upload Key Pair to Key Server</source>
+ <translation type="finished">Cargar un par de claves para clave del servidor</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/>
<source>Update Key Pair</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Actualizar par de claves</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/>
+ <source>Generate revocation certificate</source>
+ <translation type="finished">Generar certificado de revocación</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/>
+ <source>Revocation Certificates</source>
+ <translation type="finished">Certificados de revocación</translation>
</message>
</context>
<context>
@@ -1417,87 +1487,87 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="37"/>
<source>Generate A New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generar una nueva subclave</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
<source>Key ID: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">ID clave:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
<source>Algorithm: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Algoritmo:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
<source>Key Size:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tamaño de la llave:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
<source>Usage: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Uso:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
<source>Expires On </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Expira el</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
<source>Last Update: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Última actualización:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
<source>Existence: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Existencia:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/>
<source>Fingerprint: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Huella dactilar:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Subkey ID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">ID de suba</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Key Size</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tamaño de la llave</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Algo</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Algo</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Create Date</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Fecha de Creación</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Fecha de caducidad</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nunca expira</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/>
<source>Never Expires</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nunca expira</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/>
<source>Edit Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Editar fecha de vencimiento</translation>
</message>
</context>
<context>
@@ -1505,192 +1575,202 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="39"/>
<source>New UID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nuevo uid</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="40"/>
<source>UID Management</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Gestión UID</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/>
+ <source>UIDs</source>
+ <translation type="finished">Uids</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/>
+ <source>Signature of Selected UID</source>
+ <translation type="finished">Firma de UID seleccionado</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Select</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Seleccione</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nombre</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Correo electrónico</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Comment</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Comentario</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Key ID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">ID clave</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Create Date</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Fecha de Creación</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Expired Date</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Fecha de vencimiento</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/>
<source>Never Expires</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nunca expira</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación inválida</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/>
<source>Please select one or more UIDs before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Seleccione uno o más UID antes de hacer esta operación.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/>
<source>Sign Selected UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Signo de uid seleccionado (s)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/>
<source>Delete Selected UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar UID seleccionado (s)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/>
<source>Successful Operation</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación exitosa</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
<source>Successfully added a new UID.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Agregó con éxito un nuevo UID.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/>
<source>Operation Failed</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación fallida</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/>
<source>An error occurred during the operation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Se produjo un error durante la operación.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/>
<source>Deleting UIDs</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar UIDS</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/>
<source>Are you sure that you want to delete the following uids?</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">¿Está seguro de que desea eliminar los siguientes uids?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/>
<source>The action can not be undone.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">La acción no se puede deshacer.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/>
<source>Set Primary UID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Establecer uid primario</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/>
<source>Are you sure that you want to set the Primary UID to?</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">¿Está seguro de que desea configurar el UID primario para?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/>
<source>Set As Primary</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Establecer como primario</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/>
<source>Sign UID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Muestra uid</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/>
<source>Delete UID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar uid</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/>
<source>Please select one UID before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Por favor, seleccione una UID antes de hacer esta operación.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/>
<source>Deleting UID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar uid</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/>
<source>Are you sure that you want to delete the following uid?</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">¿Está seguro de que desea eliminar el siguiente UID?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/>
<source>Delete(Revoke) Key Signature</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar (revocar) Firma clave</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/>
<source>Please select one Key Signature before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Seleccione una firma clave antes de hacer esta operación.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/>
<source>To delete the signature, you need to have its corresponding public key in the local database.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Para eliminar la firma, debe tener su clave pública correspondiente en la base de datos local.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/>
<source>Deleting Key Signature</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Eliminar la firma clave</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/>
<source>Are you sure that you want to delete the following signature?</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">¿Está seguro de que desea eliminar la siguiente firma?</translation>
</message>
</context>
<context>
@@ -1698,140 +1778,140 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="40"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Cerca</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="41"/>
<source>&amp;Import ALL</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">E importar todos</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="42"/>
<source>&amp;Search</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Buscar</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="45"/>
<source>Search String:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cadena de búsqueda:</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="49"/>
<source>Key Server:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Servidor de teclas:</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="97"/>
<source>Update Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Actualizar las teclas de Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="99"/>
<source>Import Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar claves de Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>UID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Uid</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>Creation date</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Fecha de creación</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>KeyID</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Keyid</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>Tag</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Etiqueta</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/>
- <source>&lt;h4&gt;Text is empty.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Text is empty.</source>
+ <translation type="finished">El texto está vacío.</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/>
<source>Not Key Found</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No se encuentra clave</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/>
<source>Timeout</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Se acabó el tiempo</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/>
<source>Key Server Not Found</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Servidor de teclas no encontrado</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/>
<source>Connection Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error de conexión</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/>
- <source>&lt;h4&gt;CToo many responses from keyserver!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Too many responses from keyserver!</source>
+ <translation type="finished">Demasiadas respuestas de Keyserver!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/>
- <source>&lt;h4&gt;No keys found, input may be kexId, retrying search with 0x.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>No keys found, input may be kexId, retrying search with 0x.</source>
+ <translation type="finished">No se han encontrado llaves, la entrada puede ser kexid, volviendo a intentar la búsqueda con 0x.</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/>
- <source>&lt;h4&gt;No keys found containing the search string!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>No keys found containing the search string!</source>
+ <translation type="finished">¡No se han encontrado llaves que contengan la cadena de búsqueda!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/>
- <source>&lt;h4&gt;Insufficiently specific search string!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Insufficiently specific search string!</source>
+ <translation type="finished">Insuficientemente específica de la cadena de búsqueda!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="274"/>
<source>revoked</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="277"/>
<source>disabled</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="317"/>
<source>&lt;h4&gt;%1 keys found. Double click a key to import it.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&lt;h4&gt;% 1 llaves encontradas.Haga doble clic en una tecla para importarlo. &lt;/ H4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="383"/>
<source>Key Not Found</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave no encontrada</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="410"/>
<source>&lt;h4&gt;Key Updated&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&lt;H4&gt; Tecla actualizada &lt;/ h4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="412"/>
<source>&lt;h4&gt;Key Imported&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&lt;H4&gt; Clave importado &lt;/ h4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="473"/>
<source>Upload Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Subir claves de Keyserver</translation>
</message>
</context>
<context>
@@ -1839,22 +1919,22 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="36"/>
<source>Confirm</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Confirmar</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="41"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nunca expira</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="61"/>
<source>Operation Failed</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación fallida</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="62"/>
<source>An error occurred during the operation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Se produjo un error durante la operación.</translation>
</message>
</context>
<context>
@@ -1862,801 +1942,856 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="72"/>
<source>Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Fecha de caducidad</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="81"/>
- <source>Sign For Key&apos;s UID(s)</source>
- <translation type="unfinished"></translation>
+ <source>Sign For Key's UID(s)</source>
+ <translation type="finished">Signo para uid (s) de clave (s)</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="100"/>
<source>Unsuccessful Operation</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación fallida</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="101"/>
<source>Signature operation failed for UID </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">La operación de la firma falló por UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="108"/>
<source>Operation Complete</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación completa</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="109"/>
<source>The signature operation of the UID is complete</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">El funcionamiento de la firma del UID está completo.</translation>
</message>
</context>
<context>
<name>KeyUploadDialog</name>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/>
<source>Uploading Public Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Subiendo la clave pública</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/>
<source>Key Not Found</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave no encontrada</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/>
<source>Timeout</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Se acabó el tiempo</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/>
<source>Key Server Not Found</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Servidor de teclas no encontrado</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/>
<source>Connection Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error de conexión</translation>
</message>
</context>
<context>
<name>KeyserverTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="508"/>
- <source>Default Keyserver for import:</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="607"/>
+ <source>Default Key Server for import:</source>
+ <translation type="finished">Servidor de tecla predeterminado para importar:</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="525"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="624"/>
<source>Add</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Agregar</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/>
+ <location filename="../../src/MainWindow.cpp" line="35"/>
+ <source>Loading Gnupg</source>
+ <translation type="finished">Cargando gnupg</translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="62"/>
+ <source>ENV Loading Failed</source>
+ <translation type="finished">Enviando env falla</translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="63"/>
+ <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
+ <translation type="finished">GNUPG no está instalado correctamente, siga las instrucciones de README para instalar GNUPG y luego abrir GPGFRontend.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/>
<source>No Key Selected</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Sin llave seleccionada</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación inválida</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/>
<source>The selected key contains a key that does not actually have a encrypt usage.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">La clave seleccionada contiene una clave que en realidad no tiene un uso de cifrado. &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/>
+ <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
+ <translation type="finished">&lt;br/&gt; Por ejemplo, la siguiente clave: &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/>
+ <source>Encrypting</source>
+ <translation type="unfinished"/>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/>
+ <source>Function Disabled</source>
+ <translation type="finished">Función desactivada</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/>
+ <source>Please go to the settings interface to enable and configure this function.</source>
+ <translation type="finished">Por favor, vaya a la interfaz de configuración para habilitar y configurar esta función.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/>
<source>The selected key contains a key that does not actually have a signature usage.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">La clave seleccionada contiene una clave que en realidad no tiene un uso de la firma. &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/>
+ <source>Signing</source>
+ <translation type="finished">Firma</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/>
+ <source>Decrypting</source>
+ <translation type="unfinished"/>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/>
+ <source>Verifying</source>
+ <translation type="finished">Verificar</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/>
<source>Invalid KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Teclado no válido</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/>
<source>The selected keypair cannot be used for signing and encryption at the same time.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">El teclado seleccionado no se puede utilizar para la firma y el cifrado al mismo tiempo. &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/>
<source>Incomplete Operation</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Operación incompleta</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/>
<source>None of the selected key pairs can provide the encryption function.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ninguno de los pares de teclas seleccionados puede proporcionar la función de cifrado.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/>
<source>None of the selected key pairs can provide the signature function.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ninguno de los pares de teclas seleccionados puede proporcionar la función de firma.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/>
+ <source>Encrypting and Signing</source>
+ <translation type="finished">Cifrado y firma</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/>
+ <source>Decrypting and Verifying</source>
+ <translation type="finished">Descifrar y verificar</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <source>Select a file before doing it.</source>
+ <translation type="finished">Seleccione un archivo antes de hacerlo.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
<source>No permission to read this file.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No hay permiso para leer este archivo.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
<source>No permission to create file.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No hay permiso para crear un archivo.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Advertencia</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/>
<source>The target file already exists, do you need to overwrite it?</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">El archivo objetivo ya existe, ¿necesita sobrescribirlo?</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>An error occurred during operation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Se produjo un error durante la operación.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/>
<source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Por favor, seleccione el archivo de destino o firma apropiado.Asegúrese de que ambos estén en este directorio.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
<source>No permission to read target file.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No hay permiso para leer el archivo de destino.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
<source>No permission to read signature file.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No hay permiso para leer el archivo de firma.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
<source>Select a file(.gpg/.asc) before doing it.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Seleccione un archivo (.gpg / .asc) antes de hacerlo.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/>
- <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/>
+ <source>Outdated Version</source>
+ <translation type="finished">Versión desactualizada</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
- <source>Select a file before doing it.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/>
+ <source>This version(%1) is out of date, please update the latest version in time. </source>
+ <translation type="finished">Esta versión (% 1) está desactualizada, actualice la última versión en el tiempo.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/>
+ <source>You can download the latest version(%1) on Github Releases Page.&lt;br/&gt;</source>
+ <translation type="finished">Puede descargar la última versión (% 1) en la página de lanzamientos GitHub. &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/>
+ <source>Unreleased Version</source>
+ <translation type="finished">Versión inédita</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/>
+ <source>This version(%1) has not been officially released and is not recommended for use in a production environment. &lt;br/&gt;</source>
+ <translation type="finished">Esta versión (% 1) no se ha liberado oficialmente y no se recomienda para su uso en un entorno de producción.&lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/>
<source>There is one unencrypted file in attachment folder</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Hay un archivo sin cifrado en la carpeta de archivos adjuntos</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source>There are </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Existen</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source> unencrypted files in attachment folder</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivos sin cifrar en la carpeta ADJUNTO</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="30"/>
<source>&amp;New</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="36"/>
<source>Open a new file</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abrir un nuevo archivo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="39"/>
<source>&amp;Open...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Abierto...</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="42"/>
<source>Open an existing file</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abra un archivo existente</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="45"/>
<source>&amp;Browser</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="47"/>
<source>Open a file browser</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abra un navegador de archivos</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="50"/>
<source>&amp;Save</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Ahorrar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="53"/>
<source>Save the current File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Guarda el archivo actual</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="56"/>
<source>Save &amp;As</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Guardar como</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="59"/>
<source>Save the current File as...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Guarde el archivo actual como ...</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="62"/>
<source>&amp;Print</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Impresión</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="65"/>
<source>Print Document</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Imprimir documento</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="68"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Cerca</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="70"/>
<source>Close file</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cerrar el archivo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="73"/>
<source>&amp;Quit</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Dejar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="76"/>
<source>Quit Program</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Programa de dejar de fumar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="81"/>
<source>&amp;Undo</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Deshacer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="83"/>
<source>Undo Last Edit Action</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Deshacer Última edición de acción</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="86"/>
<source>&amp;Redo</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Rehacer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="88"/>
<source>Redo Last Edit Action</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Rehacer la última acción de edición</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="91"/>
<source>Zoom In</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Acercarse</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="95"/>
<source>Zoom Out</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Disminuir el zoom</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="99"/>
<source>&amp;Paste</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Pegar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="102"/>
<source>Paste Text From Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Pegar texto del portapapeles</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="105"/>
<source>Cu&amp;t</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Con &amp; t.</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="108"/>
- <source>Cut the current selection&apos;s contents to the clipboard</source>
- <translation type="unfinished"></translation>
+ <source>Cut the current selection's contents to the clipboard</source>
+ <translation type="finished">Cortar los contenidos de la selección actual al portapapeles.</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="112"/>
<source>&amp;Copy</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Dupdo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="115"/>
- <source>Copy the current selection&apos;s contents to the clipboard</source>
- <translation type="unfinished"></translation>
+ <source>Copy the current selection's contents to the clipboard</source>
+ <translation type="finished">Copia los contenidos de la selección actual al portapapeles.</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="119"/>
<source>&amp;Quote</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp; quot</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="121"/>
<source>Quote whole text</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cita todo el texto</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="124"/>
<source>Select &amp;All</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Seleccionar todo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="127"/>
<source>Select the whole text</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Seleccione todo el texto</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="130"/>
<source>&amp;Find</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Encontrar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="132"/>
<source>Find a word</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Encontrar una palabra</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="135"/>
<source>Remove &amp;spacing</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Retirar y espaciar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="138"/>
<source>Remove double linebreaks, e.g. in pasted text from webmailer</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Retire las letras dobles, por ejemplo.En texto pegado desde Webmailer.</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="141"/>
<source>Se&amp;ttings</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Y tutting</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="142"/>
<source>Open settings dialog</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abrir configuración de diálogo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="148"/>
<source>&amp;Encrypt</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Y cifrar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="151"/>
<source>Encrypt Message</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cifrar mensaje</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="154"/>
<source>&amp;Encrypt &amp;Sign</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp; Cifrar y firmar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="157"/>
<source>Encrypt and Sign Message</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cifrar y firmar mensaje</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="160"/>
<source>&amp;Decrypt</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Y descifrar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="163"/>
<source>Decrypt Message</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Mensaje de descifra</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="166"/>
<source>&amp;Decrypt &amp;Verify</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Y descifrar y verificar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="169"/>
<source>Decrypt and Verify Message</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Descifrar y verificar el mensaje</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="175"/>
<source>&amp;Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cifrar archivo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="176"/>
<source>Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cifrar archivo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="179"/>
<source>&amp;Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo de descifrado</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="180"/>
<source>Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo de descifrado</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="183"/>
<source>&amp;Sign File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Y firmar archivo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="184"/>
<source>Sign File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo de firma</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="187"/>
<source>&amp;Verify File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Y verificar el archivo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="188"/>
<source>Verify File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Verificar archivo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="192"/>
<source>&amp;Sign</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Firmar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="195"/>
<source>Sign Message</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Mensaje de signo</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="198"/>
<source>&amp;Verify</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Verificar</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="201"/>
<source>Verify Message</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Verificar mensaje</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="207"/>
<source>&amp;Editor</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="209"/>
<source>Import New Key From Editor</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Importar nueva clave del editor</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/>
- <source>Manage &amp;keys</source>
- <translation type="unfinished"></translation>
+ <source>Manage &amp;Keys</source>
+ <translation type="finished">Gestión y llaves</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="214"/>
<source>Open Keymanagement</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">MANIFICACIÓN ABIERTA</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/>
<source>&amp;About</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Acerca de</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/>
+ <source>Show the application's About box</source>
+ <translation type="finished">Muestra la siguiente aplicación</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/>
- <source>Show the application&apos;s About box</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/>
+ <source>&amp;Check for Updates</source>
+ <translation type="finished">Compruebe las actualizaciones</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <source>Check for updates</source>
+ <translation type="finished">Compruebe las actualizaciones</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/>
<source>Open &amp;Wizard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abierto y asistente</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
<source>Open the wizard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abrir el asistente</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
<source>Append Selected Key(s) To Text</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Anexar la (s) clave (s) seleccionada (s) al texto</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
<source>Append The Selected Keys To Text in Editor</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Anexar las teclas seleccionadas al texto en el editor</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
- <source>Copy EMail-address</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <source>Copy Email</source>
+ <translation type="finished">Copiar el correo electrónico</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/>
- <source>Copy selected EMailaddress to clipboard</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <source>Copy selected Email to clipboard</source>
+ <translation type="finished">Copia el correo electrónico seleccionado al portapapeles.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
<source>Show Key Details</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Mostrar detalles clave</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/>
<source>Show Details for this Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Mostrar detalles para esta clave</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/>
<source>Refresh Key From Key Server</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Actualizar la llave del servidor clave</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/>
<source>Refresh key from default key server</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Actualizar la tecla del servidor de clave predeterminado</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/>
<source>Upload Public Key(s) To Server</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cargar la (s) clave pública al servidor</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/>
<source>Upload The Selected Public Keys To Server</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Sube las claves públicas seleccionadas para el servidor</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/>
<source>Remove PGP Header</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Retire el encabezado PGP</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/>
<source>Add PGP Header</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Añadir PGP Encabezado</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/>
<source>&amp;File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Archivo</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/>
<source>&amp;Edit</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Editar</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/>
<source>&amp;File...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Archivo...</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/>
<source>&amp;Crypt</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Cripta</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
<source>&amp;Keys</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Llaves</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/>
<source>&amp;Import Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">E importar clave</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/>
<source>&amp;Steganography</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Steganography</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
<source>&amp;View</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Vista</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/>
<source>&amp;Help</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&amp;Ayudar</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/>
<source>File</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivo</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/>
<source>Crypt</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Cripta</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/>
<source>Key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/>
<source>Edit</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Editar</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/>
<source>Special Edit</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Edición especial</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/>
<source>Import key from...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave de importación de ...</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/>
<source>Import key</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tecla de importación</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/>
<source>Browser to view and operate file</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Navegador para ver y operar el archivo</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/>
<source>Browser</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/>
<source>Ready</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Listo</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/>
<source>Key ToolBox</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Caja de herramientas clave</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/>
<source>Information Board</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/>
- <source>Attached files:</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>MimeTab</name>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
- <source>Decode quoted printable</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="292"/>
- <source>Try to recognize quoted printable.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="296"/>
- <source>Parse PGP/MIME (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="299"/>
- <source>Try to split attachments from PGP-MIME ecrypted messages.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="304"/>
- <source>Open with external application (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="306"/>
- <source>Open attachments with default application for the filetype.&lt;br&gt; There are at least two possible problems with this behaviour:&lt;ol&gt;&lt;li&gt;File needs to be saved unencrypted to attachments folder.&lt;br&gt; Its your job to clean this folder.&lt;/li&gt;&lt;li&gt;The external application may have its own temp files.&lt;/li&gt;&lt;/ol&gt;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
- <source>Enable opening with external applications.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tarjeta de la información</translation>
</message>
</context>
<context>
@@ -2664,107 +2799,107 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/gpg/result_analyse/DecryptResultAnalyse.cpp" line="42"/>
<source>&gt;Recipient: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">&gt; Recipiente:</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="35"/>
<source>One or More Bad Signatures.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Una o más firmas malas.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="40"/>
<source>A </source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="42"/>
<source>Good </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Bien</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="45"/>
<source>Bad </source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="48"/>
<source>Expired </source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="51"/>
- <source>Missing Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <source>Missing Key's </source>
+ <translation type="finished">Llaves perdidas</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="54"/>
- <source>Revoked Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <source>Revoked Key's </source>
+ <translation type="finished">Clave revocada</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="57"/>
- <source>Expired Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <source>Expired Key's </source>
+ <translation type="finished">Key caducado</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="60"/>
- <source>Missing CRL&apos;s </source>
- <translation type="unfinished"></translation>
+ <source>Missing CRL's </source>
+ <translation type="finished">Falta CRL</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="64"/>
<source>Signature Fully Valid.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Firma totalmente válida.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="66"/>
<source>Signature NOT Fully Valid.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Firma no completamente válida.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="74"/>
<source>Key is NOT present with ID 0x</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">La llave no está presente con ID 0x</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="81"/>
<source>A signature could NOT be verified due to a Missing Key
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No se pudo verificar una firma debido a una llave faltante.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="85"/>
<source>A signature is valid but the key used to verify the signature has been revoked
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Una firma es válida, pero la clave utilizada para verificar la firma ha sido revocada</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="93"/>
<source>A signature is valid but expired
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Una firma es válida pero caducada.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="100"/>
<source>A signature is valid but the key used to verify the signature has expired.
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Una firma es válida, pero la clave utilizada para verificar la firma ha caducado.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="107"/>
<source>There was some other error which prevented the signature verification.
</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Hubo algún otro error que impidió la verificación de la firma.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="113"/>
<source>Error for key with fingerprint </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error a la llave con la huella digital</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="128"/>
<source>Signed By: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Firmado por:</translation>
</message>
</context>
<context>
@@ -2772,60 +2907,193 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="29"/>
<source>Unsaved Files</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Archivos no guardados</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="77"/>
- <source>&lt;h3&gt;%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?&lt;/h3&gt;</source>
- <translation type="unfinished"></translation>
+ <source>%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?</source>
+ <translation type="finished">% 1 Los archivos contienen información no guardada. &lt;br/&gt; ¡Guarda los cambios antes de cerrar?</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="88"/>
<source>Check the files you want to save:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Compruebe los archivos que desea guardar:</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="89"/>
- <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <source>&lt;b&gt;Note:&lt;/b&gt; If you don't save these files, all changes are lost.&lt;br/&gt;</source>
+ <translation type="finished">&lt;b&gt; Nota: &lt;/ b&gt; Si no guarda estos archivos, todos los cambios se pierden. &lt;br/&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>SendMailDialog</name>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="35"/>
+ <source>Incomplete configuration</source>
+ <translation type="finished">Configuración incompleta</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="36"/>
+ <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source>
+ <translation type="finished">La dirección SMTP está vacía, vaya a la interfaz de configuración para completar la configuración.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="86"/>
+ <source> Recipient cannot be empty
+</source>
+ <translation type="finished">El destinatario no puede estar vacío</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="91"/>
+ <source> One or more Recipient's Email Address is invalid
+</source>
+ <translation type="finished">Una o más dirección de correo electrónico del destinatario no es válida</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="97"/>
+ <source> Sender cannot be empty
+</source>
+ <translation type="finished">El remitente no puede estar vacío</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="99"/>
+ <source> Sender's Email Address is invalid
+</source>
+ <translation type="finished">La dirección de correo electrónico del remitente no es válida</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail</source>
+ <translation type="finished">Fallar</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation type="finished">Falla en conectar el servidor SMTP</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <source>Fail to Login into SMTP Server</source>
+ <translation type="finished">No iniciar sesión en el servidor SMTP</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail to Send Mail to SMTP Server</source>
+ <translation type="finished">No enviar correo al servidor SMTP</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Success</source>
+ <translation type="finished">Éxito</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Succeed in Sending Mail to SMTP Server</source>
+ <translation type="finished">Tener éxito en enviar correo al servidor SMTP</translation>
+ </message>
+</context>
+<context>
+ <name>SendMailTab</name>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
+ <source>Enable</source>
+ <translation type="finished">Permitir</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="311"/>
+ <source>SMTP Address</source>
+ <translation type="finished">Dirección SMTP</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="313"/>
+ <source>Username</source>
+ <translation type="finished">Nombre de usuario</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
+ <source>Password</source>
+ <translation type="finished">Contraseña</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="317"/>
+ <source>Port</source>
+ <translation type="finished">Puerto</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="319"/>
+ <source>Connection Security</source>
+ <translation type="finished">Seguridad de la conexión</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="322"/>
+ <source>Default Sender</source>
+ <translation type="finished">Remitente predeterminado</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail</source>
+ <translation type="finished">Fallar</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation type="finished">Falla en conectar el servidor SMTP</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail to Login</source>
+ <translation type="finished">Falla en iniciar sesión</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Success</source>
+ <translation type="finished">Éxito</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Succeed in connecting and login</source>
+ <translation type="finished">Tener éxito en la conexión e inicio de sesión</translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="38"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
<source>General</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">General</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="39"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
<source>Appearance</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Apariencia</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
- <source>PGP/Mime</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="42"/>
+ <source>Send Mail</source>
+ <translation type="finished">Enviar correo</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
<source>Key Server</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Servidor clave</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="45"/>
<source>Advanced</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="56"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="58"/>
<source>Settings</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Ajustes</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="101"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="103"/>
<source>System Default</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Sistema por defecto</translation>
</message>
</context>
<context>
@@ -2833,62 +3101,62 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="46"/>
<source>Generate New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generar nueva subclave</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="61"/>
<source>Encryption</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="64"/>
<source>Signing</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Firma</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="67"/>
<source>Certification</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Certificación</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="70"/>
<source>Authentication</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Autenticación</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="114"/>
<source>Expiration Date:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Fecha de caducidad:</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="115"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nunca expira</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="116"/>
<source>KeySize (in Bit):</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Keysize (en bit):</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="117"/>
<source>Key Type:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tipo de llave:</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="126"/>
<source>Basic Information</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Información básica</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="214"/>
<source> Expiration time no more than 2 years. </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Tiempo de vencimiento No más de 2 años.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="235"/>
<source>Generating Subkey...</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Generando Subkey ...</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="238"/>
@@ -2896,90 +3164,129 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
This may take a while.
To speed up the process use your computer
(e.g. browse the net, listen to music,...)</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Recogiendo datos aleatorios para la generación de suba.
+ Esto puede tardar un rato.
+ Para acelerar el proceso, use su computadora.
+ (Por ejemplo, navega por la red, escucha música, ...)</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/>
<source>Success</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Éxito</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/>
<source>The new subkey has been generated.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">La nueva subclave ha sido generada.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/>
<source>Failure</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Falla</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/>
<source>An error occurred during subkey generation.</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Se produjo un error durante la generación de sujetas.</translation>
</message>
</context>
<context>
<name>TextEdit</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/>
<source>untitled</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Advertencia</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/>
+ <source>Cannot read file %1:
+%2.</source>
+ <translation type="finished">No se puede leer el archivo% 1:
+% 2.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/>
<source>Open file</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Abrir documento</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/>
+ <source>File</source>
+ <translation type="finished">Archivo</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/>
+ <source>Cannot write file %1:
+%2.</source>
+ <translation type="finished">No se puede escribir archivo% 1:
+% 2.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
<source>Save file</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Guardar el archivo</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/>
+ <source>Unsaved document</source>
+ <translation type="finished">Documento no guardado</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/>
+ <source>The document &quot;%1&quot; has been modified. Do you want to save your changes?&lt;br/&gt;</source>
+ <translation type="finished">El documento &quot;% 1&quot; ha sido modificado.¿Quieres guardar tus cambios? &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/>
+ <source>&lt;b&gt;Note:&lt;/b&gt; If you don't save these files, all changes are lost.&lt;br/&gt;</source>
+ <translation type="finished">&lt;b&gt; Nota: &lt;/ b&gt; Si no guarda estos archivos, todos los cambios se pierden. &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/>
<source>Application</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Solicitud</translation>
</message>
+</context>
+<context>
+ <name>UpdateTab</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/>
- <source>Cannot read file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/>
+ <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source>
+ <translation type="finished">Se recomienda que siempre revise la versión de GPGFRontend y actualice a la última versión.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/>
- <source>File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/>
+ <source>New versions not only represent new features, but also often represent functional and security fixes.</source>
+ <translation type="finished">Las nuevas versiones no solo representan nuevas características, sino que también representan correcciones funcionales y de seguridad.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/>
- <source>Cannot write file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/>
+ <source>Current Version: </source>
+ <translation type="finished">Versión actual:</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/>
- <source>Unsaved document</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/>
+ <source>The current version is inconsistent with the latest version on github.</source>
+ <translation type="finished">La versión actual es inconsistente con la última versión en GitHub.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/>
- <source>&lt;h3&gt;The document &quot;%1&quot; has been modified.&lt;br/&gt;Do you want to save your changes?&lt;/h3&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/>
+ <source>Please click &lt;a href=&quot;https://github.com/saturneric/GpgFrontend/releases&quot;&gt;here&lt;/a&gt; to download the latest version.</source>
+ <translation type="finished">Haga clic en &lt;a href=&quot;https://github.com/saturnic/gpgfrontend/releseses&quot;&gt; aquí &lt;/a&gt; para descargar la última versión.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
- <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/>
+ <source>Latest Version From Github: </source>
+ <translation type="finished">Última versión de GitHub:</translation>
</message>
</context>
<context>
@@ -2987,32 +3294,32 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="32"/>
<source>Signature Details</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Detalles de la firma</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="53"/>
<source>Status: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado:</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="56"/>
<source>No valid input found</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No se ha encontrado ninguna entrada válida</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="67"/>
<source>Error Validating signature</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error al validar la firma</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="70"/>
<source>File was signed on %1 &lt;br/&gt; It Contains:&lt;br/&gt;&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">El archivo se firmó en% 1 &lt;br/&gt;, contiene: &lt;br/&gt; &lt;br/&gt;</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="72"/>
<source>Signed on %1 &lt;br/&gt; It Contains:&lt;br /&gt;&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Firmado en% 1 &lt;br/&gt; contiene: &lt;br /&gt; &lt;br/&gt;</translation>
</message>
</context>
<context>
@@ -3020,22 +3327,22 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="36"/>
<source>Import from keyserver</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Import desde Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="39"/>
<source>Key not present with id 0x</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Llave no presente con id 0x</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="43"/>
<source>Status:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="45"/>
<source>Key not present in keylist</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Llave no presente en el keylist</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="58"/>
@@ -3045,7 +3352,7 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="115"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="129"/>
<source>Key Information is NOT Available</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">La información clave no está disponible</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="60"/>
@@ -3055,103 +3362,103 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="117"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="131"/>
<source>Fingerprint: </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Huella dactilar:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="67"/>
<source>Status: Cert Revoked</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado: CERT REVOCED</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="81"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="95"/>
<source>Status: Signature Expired</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado: Firma expiró</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="96"/>
<source>Status: Key Expired</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado: clave expirada</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="110"/>
<source>Status: General Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado: Error general</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="124"/>
<source>Status: Unknown Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Estado: error desconocido</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="159"/>
<source>Signer Name:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Nombre del firmante:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="160"/>
<source>Signer Email:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Correo electrónico del firmante:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="161"/>
- <source>Key&apos;s Fingerprint:</source>
- <translation type="unfinished"></translation>
+ <source>Key's Fingerprint:</source>
+ <translation type="finished">Huella digital de la llave:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="162"/>
<source>Valid:</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="163"/>
<source>Flags:</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Banderas:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="171"/>
<source>Fully Valid</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Completamente válido</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="173"/>
<source>NOT Fully Valid</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">No completamente válido</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="180"/>
<source>Good </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Bien</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="183"/>
<source>Bad </source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="186"/>
<source>Expired </source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished"/>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="189"/>
<source>Missing Key </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Llave faltante</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="192"/>
<source>Revoked Key </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave revocada</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="195"/>
<source>Expired Key </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Clave caducada</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="198"/>
<source>Missing CRL </source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Falta CRL</translation>
</message>
</context>
<context>
@@ -3159,33 +3466,33 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/Wizard.cpp" line="46"/>
<source>First Start Wizard</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Asistente de primer inicio</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="76"/>
<source>Import Error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error de importación</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="76"/>
- <source>Couldn&apos;t locate any keyring file in %1</source>
- <translation type="unfinished"></translation>
+ <source>Couldn't locate any keyring file in %1</source>
+ <translation type="finished">No se pudo localizar ningún archivo de llaves en% 1</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="84"/>
<location filename="../../src/ui/Wizard.cpp" line="95"/>
<source>Import error</source>
- <translation type="unfinished"></translation>
+ <translation type="finished">Error de importación</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="85"/>
- <source>Couldn&apos;t open private keyringfile: %1</source>
- <translation type="unfinished"></translation>
+ <source>Couldn't open private keyringfile: %1</source>
+ <translation type="finished">No se pudo abrir el archivo de llavero privado:% 1</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="96"/>
- <source>Couldn&apos;t open public keyringfile: %1</source>
- <translation type="unfinished"></translation>
+ <source>Couldn't open public keyringfile: %1</source>
+ <translation type="finished">No se pudo abrir el archivo de llavero público:% 1</translation>
</message>
</context>
-</TS>
+</TS> \ No newline at end of file
diff --git a/resource/ts/gpg_frontend_fr.ts b/resource/ts/gpgfrontend_fr.ts
index a32fcc56..fe49011a 100644
--- a/resource/ts/gpg_frontend_fr.ts
+++ b/resource/ts/gpgfrontend_fr.ts
@@ -4,212 +4,197 @@
<context>
<name>AboutDialog</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="29"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/>
<source>About </source>
- <translation type="unfinished"></translation>
+ <translation>À propos</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="35"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/>
<source>General</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="36"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/>
<source>Translators</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/>
+ <source>Update</source>
+ <translation>Mettre à jour</translation>
+ </message>
</context>
<context>
<name>AdvancedTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="580"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="679"/>
<source>Show Steganography Options [Advanced]</source>
- <translation type="unfinished"></translation>
+ <translation>Afficher les options de la stéganographie [avancée]</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="582"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="681"/>
<source>Show Steganographic Options.</source>
- <translation type="unfinished"></translation>
+ <translation>Afficher les options stéganographiques.</translation>
</message>
</context>
<context>
<name>AppearanceTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="368"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="444"/>
<source>Iconsize</source>
- <translation type="unfinished"></translation>
+ <translation>Isoniser.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="370"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="446"/>
<source>small</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="371"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="447"/>
<source>medium</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="372"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="448"/>
<source>large</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="388"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="464"/>
<source>Iconstyle</source>
- <translation type="unfinished"></translation>
+ <translation>Iconstyle</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="390"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="466"/>
<source>just text</source>
- <translation type="unfinished"></translation>
+ <translation>juste du texte</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="391"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="467"/>
<source>just icons</source>
- <translation type="unfinished"></translation>
+ <translation>juste des icônes</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="392"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="468"/>
<source>text and icons</source>
- <translation type="unfinished"></translation>
+ <translation>Texte et icônes</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="484"/>
<source>Windowstate</source>
- <translation type="unfinished"></translation>
+ <translation>Windowstate</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="411"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="487"/>
<source>Save window size and position on exit.</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer la taille de la fenêtre et la position à la sortie.</translation>
</message>
-</context>
-<context>
- <name>AttachmentTableModel</name>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/>
- <source>Filename</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="495"/>
+ <source>Information Board</source>
+ <translation>Tableau d&apos;information</translation>
</message>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/>
- <source>Contenttype</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="501"/>
+ <source> Front Size</source>
+ <translation>Taille avant</translation>
</message>
</context>
<context>
- <name>Attachments</name>
- <message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/>
- <source>Save File</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/>
- <source>Save this file</source>
- <translation type="unfinished"></translation>
- </message>
+ <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/>
- <source>Open File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="165"/>
+ <source>Choose your action...</source>
+ <translation>Choisissez votre action ...</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/>
- <source>Open this file</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="166"/>
+ <source>...by clicking on the appropriate link.</source>
+ <translation>... En cliquant sur le lien approprié.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/>
- <source>File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="168"/>
+ <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
+ <translation>Si vous n&apos;avez jamais utilisé GPGFRontend avant et que vous ne possédez pas encore une clé GPG, vous pouvez éventuellement vouloir lire comment</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/>
- <source>Cannot write file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="170"/>
+ <source>Generate Key</source>
+ <translation>Générer une clé</translation>
</message>
-</context>
-<context>
- <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="161"/>
- <source>Choose your action...</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="176"/>
+ <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source>
+ <translation>Si vous souhaitez apprendre à crypter, déchiffrer, signer et vérifier le texte, vous pouvez lire</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="162"/>
- <source>...by clicking on the appropriate link.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <source>Encrypt &amp; Decrypt Text</source>
+ <translation>Texte de chiffrement et de déchiffrement</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="164"/>
- <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>or</source>
+ <translation>ou alors</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="172"/>
- <source>If you want to learn how to encrypt and decrypt text, you can read </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="180"/>
+ <source>Sign &amp; Verify Text</source>
+ <translation>Signer et vérifier le texte</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="174"/>
- <location filename="../../src/ui/Wizard.cpp" line="183"/>
- <source>this document</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="188"/>
+ <source>If you want to operate file, you can read </source>
+ <translation>Si vous souhaitez utiliser un fichier, vous pouvez lire</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="181"/>
- <source>If you want to sign and verify text, you can read </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>Encrypt &amp; Sign File</source>
+ <translation>Crypypt et fichier de signe</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="166"/>
- <source>create a new keypair</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="192"/>
+ <source>Sign &amp; Verify File</source>
+ <translation>Signez et vérifiez le fichier</translation>
</message>
</context>
<context>
<name>ConclusionPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="397"/>
+ <location filename="../../src/ui/Wizard.cpp" line="407"/>
<source>Ready.</source>
- <translation type="unfinished"></translation>
+ <translation>Prêt.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="398"/>
+ <location filename="../../src/ui/Wizard.cpp" line="408"/>
<source>Have fun with GPGFrontend!</source>
- <translation type="unfinished"></translation>
+ <translation>Amusez-vous avec GPGFrontend!</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="400"/>
+ <location filename="../../src/ui/Wizard.cpp" line="410"/>
<source>You are ready to use GPGFrontend now.&lt;br&gt;&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Vous êtes prêt à utiliser GPGFronTend maintenant. &lt;br&gt; &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="402"/>
+ <location filename="../../src/ui/Wizard.cpp" line="412"/>
<source>The Online Document</source>
- <translation type="unfinished"></translation>
+ <translation>Le document en ligne</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="403"/>
+ <location filename="../../src/ui/Wizard.cpp" line="413"/>
<source> will get you started with GPGFrontend. It will open in the main window.&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>vous fera commencer par GPGFronTend.Il s&apos;ouvrira dans la fenêtre principale. &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="410"/>
+ <location filename="../../src/ui/Wizard.cpp" line="420"/>
<source>Open offline help.</source>
- <translation type="unfinished"></translation>
+ <translation>Aide ouverte hors ligne.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="413"/>
+ <location filename="../../src/ui/Wizard.cpp" line="423"/>
<source>Dont show the wizard again.</source>
- <translation type="unfinished"></translation>
+ <translation>Ne montrez pas à nouveau l&apos;assistant.</translation>
</message>
</context>
<context>
@@ -217,129 +202,152 @@
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="32"/>
<source>Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Dossier de déchiffrement</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="34"/>
<source>Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Chiffrer</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="36"/>
<source>Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>Fichier de signe</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="38"/>
<source>Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>Vérifier le fichier</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="47"/>
<source>Input Parameters</source>
- <translation type="unfinished"></translation>
+ <translation>Paramètres d&apos;entrée</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="53"/>
<source>Target File</source>
- <translation type="unfinished"></translation>
+ <translation>Fichier cible</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="59"/>
<source>Output File</source>
- <translation type="unfinished"></translation>
+ <translation>Fichier de sortie</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="75"/>
<source>Signature File(.sig) Path</source>
- <translation type="unfinished"></translation>
+ <translation>Signature Fichier (.sig) chemin</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="134"/>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="177"/>
<source>Open File</source>
- <translation type="unfinished"></translation>
+ <translation>Fichier ouvert</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="165"/>
<source>Save File</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer le fichier</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
<source>Couldn&apos;t open file</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible d&apos;ouvrir le fichier</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/>
+ <source>Error</source>
+ <translation>Erreur</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/>
+ <source>Error Occurred During Encryption</source>
+ <translation>Une erreur s&apos;est produite lors du cryptage</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/>
+ <source>Error Occurred During Decryption</source>
+ <translation>Une erreur s&apos;est produite lors du déchiffrement</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
+ <source>Error Occurred During Signature</source>
+ <translation>Une erreur s&apos;est produite lors de la signature</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/>
<source>File</source>
- <translation type="unfinished"></translation>
+ <translation>Déposer</translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/>
<source>File exists! Do you want to overwrite it?</source>
- <translation type="unfinished"></translation>
+ <translation>Le fichier existe!Voulez-vous vous écraser?</translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/>
<source>Cannot write file %1:
%2.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible d&apos;écrire le fichier% 1:
+% 2.</translation>
</message>
</context>
<context>
<name>FilePage</name>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/>
<source>Open</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/>
<source>Delete</source>
- <translation type="unfinished"></translation>
+ <translation>Effacer</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/>
<source>Encrypt and Sign</source>
- <translation type="unfinished"></translation>
+ <translation>Chiffrer et signer</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/>
<source>Decrypt and Verify</source>
- <translation type="unfinished"></translation>
+ <translation>Déchiffrer et vérifier</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/>
<source>Only Sign</source>
- <translation type="unfinished"></translation>
+ <translation>Seulement signe</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/>
<source>Only Verify</source>
- <translation type="unfinished"></translation>
+ <translation>Vérifiez seulement</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>Avertissement</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/>
<source>Are you sure you want to delete it?</source>
- <translation type="unfinished"></translation>
+ <translation>Es-tu sûr de vouloir le supprimer?</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/>
<source>Error</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/>
<source>Unable to delete the file or folder.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de supprimer le fichier ou le dossier.</translation>
</message>
</context>
<context>
@@ -347,266 +355,281 @@
<message>
<location filename="../../src/ui/FindWidget.cpp" line="38"/>
<source>Find:</source>
- <translation type="unfinished"></translation>
+ <translation>Trouve:</translation>
</message>
</context>
<context>
<name>GeneralTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="135"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="137"/>
<source>Remember Password</source>
- <translation type="unfinished"></translation>
+ <translation>Se souvenir du mot de passe</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="138"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="140"/>
<source>Remember password until closing gpg4usb</source>
- <translation type="unfinished"></translation>
+ <translation>Rappelez-vous le mot de passe jusqu&apos;à la fermeture GPG4USB</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="145"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="147"/>
<source>Save Checked Keys</source>
- <translation type="unfinished"></translation>
+ <translation>Sauvegarder les clés cochées</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="148"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="150"/>
<source>Save checked private keys on exit and restore them on next start.</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrez des clés privées cochées sur sortie et restaurez-les au prochain démarrage.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="157"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="159"/>
<source>Confirm drag&apos;n&apos;drop key import</source>
- <translation type="unfinished"></translation>
+ <translation>Confirmer l&apos;importation principale de Drag&apos;N&apos;Drop</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="162"/>
<source>Import files dropped on the keylist without confirmation.</source>
- <translation type="unfinished"></translation>
+ <translation>Les fichiers d&apos;importation ont chuté sur la frappe sans confirmation.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="167"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="169"/>
<source>Language</source>
- <translation type="unfinished"></translation>
+ <translation>Langue</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="176"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="178"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; GpgFrontend will restart automatically if you change the language!</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;B&gt; REMARQUE: &lt;/ B&gt; GPGFRontend redémarrera automatiquement si vous changez la langue!</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="185"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="187"/>
<source>Own key</source>
- <translation type="unfinished"></translation>
+ <translation>Clé propre</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="193"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="195"/>
<source>&lt;none&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;aucun&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="207"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="209"/>
<source>Key pair for synchronization and identity authentication</source>
- <translation type="unfinished"></translation>
+ <translation>Paire de clé pour la synchronisation et l&apos;authentification d&apos;identité</translation>
</message>
</context>
<context>
<name>GpgME::GpgContext</name>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="90"/>
- <source>ENV Loading Failed</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="91"/>
- <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="577"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="528"/>
<source>Wrong password</source>
- <translation type="unfinished"></translation>
+ <translation>Mauvais mot de passe</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="585"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="536"/>
<source>Enter Password for</source>
- <translation type="unfinished"></translation>
+ <translation>Entrez le mot de passe pour</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="589"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="540"/>
<source>Enter Password</source>
- <translation type="unfinished"></translation>
+ <translation>Entrer le mot de passe</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>Key Selection</source>
- <translation type="unfinished"></translation>
+ <translation>Sélection de clé</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>No Private Key Selected</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune clé privée sélectionnée</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="804"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="746"/>
<source>Error in signing:</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur lors de la signature:</translation>
</message>
</context>
<context>
<name>GpgPathsTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="612"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="711"/>
<source>Relative path to keydb</source>
- <translation type="unfinished"></translation>
+ <translation>Chemin relatif de Keydb</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="625"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="724"/>
<source>Current keydb path: </source>
- <translation type="unfinished"></translation>
+ <translation>Chemin de Keydb actuel:</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="630"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="729"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; Gpg4usb will restart automatically if you change the keydb path!</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;B&gt; REMARQUE: &lt;/ B&gt; GPG4USB redémarrera automatiquement si vous modifiez le chemin Keydb!</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="659"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="758"/>
<source>Choose keydb directory</source>
- <translation type="unfinished"></translation>
+ <translation>Choisissez le répertoire Keydb</translation>
</message>
</context>
<context>
<name>ImportFromGnupgPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="292"/>
+ <location filename="../../src/ui/Wizard.cpp" line="302"/>
<source>Import keys...</source>
- <translation type="unfinished"></translation>
+ <translation>Keys d&apos;importation ...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="293"/>
+ <location filename="../../src/ui/Wizard.cpp" line="303"/>
<source>...from existing GnuPG installation</source>
- <translation type="unfinished"></translation>
+ <translation>... de l&apos;installation GNUPG existante</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="295"/>
+ <location filename="../../src/ui/Wizard.cpp" line="305"/>
<source>You can import keys from a locally installed GnuPG.&lt;br&gt;&lt;br&gt; The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Vous pouvez importer des clés à partir d&apos;un GNUPG installé localement. &lt;br&gt; &lt;br&gt; &lt;br&gt; L&apos;emplacement est lu depuis Registre sous Windows ou supposé être le dossier .gnupg dans votre annuaire de domicile sous Linux. &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="299"/>
+ <location filename="../../src/ui/Wizard.cpp" line="309"/>
<source>Import keys from GnuPG</source>
- <translation type="unfinished"></translation>
+ <translation>Keys d&apos;importation de gnupg</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Import Error</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur d&apos;importation</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Couldn&apos;t locate GnuPG home directory</source>
- <translation type="unfinished"></translation>
+ <translation>Ne pouvait pas localiser le répertoire de base gnupg</translation>
</message>
</context>
<context>
<name>ImportFromGpg4usbPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="215"/>
+ <location filename="../../src/ui/Wizard.cpp" line="225"/>
<source>Import from...</source>
- <translation type="unfinished"></translation>
+ <translation>Importer de...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="216"/>
+ <location filename="../../src/ui/Wizard.cpp" line="226"/>
<source>...existing GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>... GPGFronTend existant</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="218"/>
+ <location filename="../../src/ui/Wizard.cpp" line="228"/>
<source>You can import keys and/or settings from existing GPGFrontend. &lt;br&gt;&lt;br&gt;Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source>
- <translation type="unfinished"></translation>
+ <translation>Vous pouvez importer des clés et / ou des paramètres de GPGFronTend existant.&lt;br&gt; &lt;br&gt; Vérifiez simplement ce que vous souhaitez importer, cliquez sur le bouton Importer et choisissez le répertoire de votre autre GPGFronTend dans la boîte de dialogue de fichiers apparaissant.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="225"/>
+ <location filename="../../src/ui/Wizard.cpp" line="235"/>
<source>Keys</source>
- <translation type="unfinished"></translation>
+ <translation>Clés</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="229"/>
+ <location filename="../../src/ui/Wizard.cpp" line="239"/>
<source>Configuration</source>
- <translation type="unfinished"></translation>
+ <translation>Configuration</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="231"/>
+ <location filename="../../src/ui/Wizard.cpp" line="241"/>
<source>Import from GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>Importer de GPGFrontend</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="246"/>
+ <location filename="../../src/ui/Wizard.cpp" line="256"/>
<source>Other GPGFrontend directory</source>
- <translation type="unfinished"></translation>
+ <translation>Autre répertoire GPGFRONTEND</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="265"/>
+ <location filename="../../src/ui/Wizard.cpp" line="275"/>
<source>Configuration Imported</source>
- <translation type="unfinished"></translation>
+ <translation>Configuration importée</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="266"/>
+ <location filename="../../src/ui/Wizard.cpp" line="276"/>
<source>Imported Configuration from old GPGFrontend.&lt;br&gt;Will now restart to activate the configuration.</source>
- <translation type="unfinished"></translation>
+ <translation>Configuration importée d&apos;Old GPGFronTend. &lt;br&gt; va maintenant redémarrer pour activer la configuration.</translation>
</message>
</context>
<context>
<name>InfoBoardWidget</name>
<message>
- <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/>
<source>Import missing key from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Importer la clé manquante de Keyserver</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/>
+ <source>Optional Actions Menu</source>
+ <translation>Menu Actions optionnelles</translation>
</message>
</context>
<context>
<name>InfoTab</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="55"/>
- <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, &lt;br&gt;cross-platform, and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/>
+ <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, cross-platform, &lt;br&gt;and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
+ <translation>&lt;br&gt; &lt;centre&gt; GPGFronTend est un outil facile à utiliser, compact, plate-forme, &lt;br&gt; et sans installation GPG GPG GPG. Il visualise la plupart des opérations communes des commandes GPG. &lt;br&gt; Il est sous licence sous la GPL V3 &lt;br&gt; &lt;B&gt; Développeur: &lt;/ B&gt; &lt;br&gt; &lt;br&gt; Saturneric &lt;br&gt; &lt;br&gt; Si vous avez des questions ou des suggestions, soulevez un problème &lt;br/&gt; à &lt;Ahref = &quot;https://github.com/saturneric/gpgfrontend&quot;&gt; github &lt;/a&gt; ou envoyer un mail à ma liste de diffusion à &lt;a href=&quot;[email protected]&quot;&gt; [email protected] &lt;/ a&gt;.</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="63"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/>
<source>&lt;br&gt;&lt;br&gt; Built with Qt </source>
- <translation type="unfinished"></translation>
+ <translation>&lt;br&gt; &lt;br&gt; Construit avec QT</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="64"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/>
<source> and GPGME </source>
- <translation type="unfinished"></translation>
+ <translation>et gpgme</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="65"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/>
<source>&lt;br&gt;Built at </source>
- <translation type="unfinished"></translation>
+ <translation>&lt;br&gt; Construit à</translation>
</message>
</context>
<context>
<name>IntroPage</name>
<message>
<location filename="../../src/ui/Wizard.cpp" line="111"/>
- <source>Getting started...</source>
- <translation type="unfinished"></translation>
+ <source>Getting Started...</source>
+ <translation>Commencer...</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="112"/>
<source>... with GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>... avec GPGFrontend</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="114"/>
- <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.&lt;br&gt;&lt;br&gt;For more information have a look at the &lt;a href=&apos;docu_concepts.html&apos;&gt;concepts&lt;/a&gt; (by clicking the link, the page will open in the main window). &lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source>
+ <translation>Bienvenue à utiliser GPGFronTend pour le déchiffrement et la signature de texte ou de fichier!</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="123"/>
+ <location filename="../../src/ui/Wizard.cpp" line="116"/>
+ <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source>
+ <translation>est une puissante, facile à utiliser, compacte, plate-forme multiplate-forme et sans installation.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="117"/>
+ <source>For brief information have a look at the</source>
+ <translation>Pour de brèves informations, regardez le</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="118"/>
+ <source>Overview</source>
+ <translation>Aperçu</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="119"/>
+ <source>by clicking the link, the page will open in the web browser</source>
+ <translation>En cliquant sur le lien, la page s&apos;ouvrira dans le navigateur Web.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="127"/>
<source>Choose a Language</source>
- <translation type="unfinished"></translation>
+ <translation>Choisissez une langue</translation>
</message>
</context>
<context>
@@ -614,22 +637,22 @@
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="31"/>
<source>KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>Clavier</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="32"/>
<source>UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>Uids</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="33"/>
<source>Subkeys</source>
- <translation type="unfinished"></translation>
+ <translation>Souske</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="40"/>
<source>Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>Détails clés</translation>
</message>
</context>
<context>
@@ -637,150 +660,159 @@
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="32"/>
<source>Generate Key</source>
- <translation type="unfinished"></translation>
+ <translation>Générer une clé</translation>
</message>
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="68"/>
<source> Name must contain at least five characters.
</source>
- <translation type="unfinished"></translation>
+ <translation>Le nom doit contenir au moins cinq caractères.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="70"/>
<source> Please give a email address.
</source>
- <translation type="unfinished"></translation>
+ <translation>S&apos;il vous plaît donner une adresse email.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/>
- <source> Expiration time no more than 2 years. </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/>
+ <source> Expiration time no more than 2 years.
+</source>
+ <translation>Heure d&apos;expiration Pas plus de 2 ans.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/>
<source>Generating Key...</source>
- <translation type="unfinished"></translation>
+ <translation>Clé génératrice ...</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/>
<source>Collecting random data for key generation.
This may take a while.
To speed up the process use your computer
(e.g. browse the net, listen to music,...)</source>
- <translation type="unfinished"></translation>
+ <translation>Collecte de données aléatoires pour la génération de clé.
+ Cela peut prendre un peu de temps.
+ Pour accélérer le processus, utilisez votre ordinateur
+ (E.G. Parcourir le Net, écoutez de la musique, ...)</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/>
+ <source>Key Usage</source>
+ <translation>Usage de clé</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/>
<source>Encryption</source>
- <translation type="unfinished"></translation>
+ <translation>Chiffrement</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/>
<source>Signing</source>
- <translation type="unfinished"></translation>
+ <translation>Signature</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/>
<source>Certification</source>
- <translation type="unfinished"></translation>
+ <translation>Certification</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/>
<source>Authentication</source>
- <translation type="unfinished"></translation>
+ <translation>Authentification</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>Success</source>
- <translation type="unfinished"></translation>
+ <translation>Succès</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>The new key pair has been generated.</source>
- <translation type="unfinished"></translation>
+ <translation>La nouvelle paire de clés a été générée.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>Failure</source>
- <translation type="unfinished"></translation>
+ <translation>Échec</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>An error occurred during key generation.</source>
- <translation type="unfinished"></translation>
+ <translation>Une erreur s&apos;est produite lors de la génération de clé.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/>
<source>Name:</source>
- <translation type="unfinished"></translation>
+ <translation>Nom:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
<source>Email Address:</source>
- <translation type="unfinished"></translation>
+ <translation>Adresse e-mail:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
<source>Comment:</source>
- <translation type="unfinished"></translation>
+ <translation>Commenter:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
<source>Expiration Date:</source>
- <translation type="unfinished"></translation>
+ <translation>Date d&apos;expiration:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>N&apos;expire jamais</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
<source>KeySize (in Bit):</source>
- <translation type="unfinished"></translation>
+ <translation>Keysize (dans le bit):</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
<source>Key Type:</source>
- <translation type="unfinished"></translation>
+ <translation>Type de clé:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
<source>Non Pass Phrase</source>
- <translation type="unfinished"></translation>
+ <translation>Non Pass Phrase</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/>
<source>Basic Information</source>
- <translation type="unfinished"></translation>
+ <translation>Informations de base</translation>
</message>
</context>
<context>
<name>KeyGenPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="356"/>
+ <location filename="../../src/ui/Wizard.cpp" line="366"/>
<source>Create a keypair...</source>
- <translation type="unfinished"></translation>
+ <translation>Créer un keypair ...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="357"/>
+ <location filename="../../src/ui/Wizard.cpp" line="367"/>
<source>...for decrypting and signing messages</source>
- <translation type="unfinished"></translation>
+ <translation>... pour décrypter et signature des messages</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="358"/>
+ <location filename="../../src/ui/Wizard.cpp" line="368"/>
<source>You should create a new keypair.The pair consists of a public and a private key.&lt;br&gt;Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.&lt;br&gt;For more information have a look at the offline tutorial (which then is shown in the main window):</source>
- <translation type="unfinished"></translation>
+ <translation>Vous devriez créer un nouveau keypair.La Paire consiste en une clé publique et privée. &lt;br&gt; Les autres utilisateurs peuvent utiliser la clé publique pour chiffrer les messages pour vous et vérifier les messages signés par vous.Vous pouvez utiliser la clé privée pour déchiffrer et signerMessages. &lt;br&gt; Pour plus d&apos;informations, consultez le tutoriel hors ligne (qui est ensuite affiché dans la fenêtre principale):</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="365"/>
+ <location filename="../../src/ui/Wizard.cpp" line="375"/>
<source>Offline tutorial</source>
- <translation type="unfinished"></translation>
+ <translation>Tutoriel hors ligne</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="372"/>
+ <location filename="../../src/ui/Wizard.cpp" line="382"/>
<source>Create New Key</source>
- <translation type="unfinished"></translation>
+ <translation>Créer une nouvelle clé</translation>
</message>
</context>
<context>
@@ -789,83 +821,83 @@
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="53"/>
<source>Key Update Details</source>
- <translation type="unfinished"></translation>
+ <translation>Détails de la mise à jour clés</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/>
<source>No keys found</source>
- <translation type="unfinished"></translation>
+ <translation>Pas de clés trouvées</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="55"/>
<source>Key Import Details</source>
- <translation type="unfinished"></translation>
+ <translation>Détails des importations clés</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/>
<source>No keys found to import</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune clé trouvée à l&apos;importation</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="64"/>
<source>General key info</source>
- <translation type="unfinished"></translation>
+ <translation>Info général de la clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="67"/>
<source>Considered:</source>
- <translation type="unfinished"></translation>
+ <translation>Pris en considération:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="71"/>
<source>Public unchanged:</source>
- <translation type="unfinished"></translation>
+ <translation>Public inchangé:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="76"/>
<source>Imported:</source>
- <translation type="unfinished"></translation>
+ <translation>Importé:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="81"/>
<source>Not imported:</source>
- <translation type="unfinished"></translation>
+ <translation>Non importé:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="86"/>
<source>Private read:</source>
- <translation type="unfinished"></translation>
+ <translation>Lire privée:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="91"/>
<source>Private imported:</source>
- <translation type="unfinished"></translation>
+ <translation>Privé importé:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="96"/>
<source>Private unchanged:</source>
- <translation type="unfinished"></translation>
+ <translation>Privé inchangé:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>Nom</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>E-mail</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Status</source>
- <translation type="unfinished"></translation>
+ <translation>Statut</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Fingerprint</source>
- <translation type="unfinished"></translation>
+ <translation>Empreinte digitale</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="135"/>
@@ -885,22 +917,22 @@
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="144"/>
<source>new key</source>
- <translation type="unfinished"></translation>
+ <translation>nouvelle clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="147"/>
<source>new subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Nouvelle sous-clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="151"/>
<source>new signature</source>
- <translation type="unfinished"></translation>
+ <translation>nouvelle signature</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="155"/>
<source>new uid</source>
- <translation type="unfinished"></translation>
+ <translation>Nouveau UID</translation>
</message>
</context>
<context>
@@ -908,66 +940,67 @@
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Select</source>
- <translation type="unfinished"></translation>
+ <translation>Sélectionner</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Type</source>
- <translation type="unfinished"></translation>
+ <translation>Taper</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>Nom</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Email Address</source>
- <translation type="unfinished"></translation>
+ <translation>Adresse e-mail</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Usage</source>
- <translation type="unfinished"></translation>
+ <translation>Usage</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Validity</source>
- <translation type="unfinished"></translation>
+ <translation>Validité</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Finger Print</source>
- <translation type="unfinished"></translation>
+ <translation>Empreinte digitale</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
<source>Import Keys</source>
- <translation type="unfinished"></translation>
+ <translation>Clés d&apos;importation</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/>
<source>You&apos;ve dropped something on the table.
GpgFrontend will now try to import key(s).</source>
- <translation type="unfinished"></translation>
+ <translation>Vous avez laissé tomber quelque chose sur la table.
+ GPGFronTend va maintenant essayer d&apos;importer des clés (s).</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/>
<source>Always import without bothering.</source>
- <translation type="unfinished"></translation>
+ <translation>Toujours importer sans déranger.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/>
<source>Couldn&apos;t Open File: </source>
- <translation type="unfinished"></translation>
+ <translation>Impossible d&apos;ouvrir le fichier:</translation>
</message>
</context>
<context>
<name>KeyMgmt</name>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="81"/>
- <source>KeyPairs Management</source>
- <translation type="unfinished"></translation>
+ <source>Key Pair Management</source>
+ <translation>Gestion des paires de clés</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="88"/>
@@ -977,240 +1010,240 @@
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="89"/>
<source>Ctrl+O</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + o</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="90"/>
<source>Open Key File</source>
- <translation type="unfinished"></translation>
+ <translation>Ouvrir le fichier de clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="93"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Fermer</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="94"/>
<source>Ctrl+Q</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + q</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="96"/>
<source>Close</source>
- <translation type="unfinished"></translation>
+ <translation>Fermer</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="99"/>
<source>New Keypair</source>
- <translation type="unfinished"></translation>
+ <translation>Nouveau keypair</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="100"/>
<source>Ctrl+N</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + n</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="102"/>
<source>Generate KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>Générer une paire de clés</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="105"/>
<source>New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Nouvelle sous-clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="106"/>
<source>Ctrl+Shift+N</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + Maj + n</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="108"/>
<source>Generate Subkey For Selected KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>Générer de sous-clé pour sélectionner le clavier sélectionné</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="111"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="152"/>
<source>&amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Déposer</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="113"/>
<source>Import New Key From File</source>
- <translation type="unfinished"></translation>
+ <translation>Importer une nouvelle clé à partir de fichier</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="116"/>
<source>&amp;Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Presse-papiers</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="118"/>
<source>Import New Key From Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Importer une nouvelle clé de Presse-papiers</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="121"/>
<source>&amp;Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="123"/>
<source>Import New Key From Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Importer une nouvelle clé de Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="126"/>
<source>Export To &amp;Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Exporter vers le presse-papier</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="128"/>
<source>Export Selected Key(s) To Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Exporter des touches sélectionnées dans le presse-papier</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="131"/>
<source>Export To &amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>Exporter vers &amp; Fichier</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="133"/>
<source>Export Selected Key(s) To File</source>
- <translation type="unfinished"></translation>
+ <translation>Exporter la ou les touches sélectionnées dans le fichier</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="136"/>
<source>Delete Selected Key(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer la ou les touches sélectionnées</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="137"/>
<source>Delete the Selected keys</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer les touches sélectionnées</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="140"/>
<source>Delete Checked Key(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer les touches vérifiées</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="141"/>
<source>Delete the Checked keys</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer les clés cochées</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="145"/>
<source>Show Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>Afficher les détails de la clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="146"/>
<source>Show Details for this Key</source>
- <translation type="unfinished"></translation>
+ <translation>Afficher les détails de cette clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="156"/>
<source>&amp;Key</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="157"/>
<source>&amp;Generate Key</source>
- <translation type="unfinished"></translation>
+ <translation>Générer une clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="161"/>
<source>&amp;Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>Clé d&apos;importation</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="173"/>
<source>Key</source>
- <translation type="unfinished"></translation>
+ <translation>Clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="181"/>
<source>Generate</source>
- <translation type="unfinished"></translation>
+ <translation>produire</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="182"/>
<source>Generate A New Keypair or Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Générer un nouveau clavier ou une nouvelle sous-clé</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="191"/>
<source>Import key</source>
- <translation type="unfinished"></translation>
+ <translation>Clé d&apos;importation</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="192"/>
<source>Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>Clé d&apos;importation</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<source>Open Key</source>
- <translation type="unfinished"></translation>
+ <translation>Touche ouverte</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="299"/>
<source>Key Files</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers clés</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<source>Keyring files</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers de porte-clés</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="218"/>
<source>Couldn&apos;t Open File: </source>
- <translation type="unfinished"></translation>
+ <translation>Impossible d&apos;ouvrir le fichier:</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="268"/>
<source>Deleting Keys</source>
- <translation type="unfinished"></translation>
+ <translation>Suppression des clés</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="269"/>
<source>Are you sure that you want to delete the following keys?</source>
- <translation type="unfinished"></translation>
+ <translation>Êtes-vous sûr de vouloir supprimer les clés suivantes?</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="270"/>
<source>The action can not be undone.</source>
- <translation type="unfinished"></translation>
+ <translation>L&apos;action ne peut pas être annulée.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="299"/>
<source>Export Key To File</source>
- <translation type="unfinished"></translation>
+ <translation>Exporter la clé pour déposer</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="309"/>
<source>key(s) exported</source>
- <translation type="unfinished"></translation>
+ <translation>clé (s) exportée (s)</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="338"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="345"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Opération invalide</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="339"/>
<source>Please select one KeyPair before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Veuillez sélectionner un clavier avant de faire cette opération.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="346"/>
<source>If a key pair does not have a private key then it will not be able to generate sub-keys.</source>
- <translation type="unfinished"></translation>
+ <translation>Si une paire de clés n&apos;a pas de clé privée, elle ne pourra pas générer des sous-clés.</translation>
</message>
</context>
<context>
@@ -1218,198 +1251,237 @@
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="40"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>Nom</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="41"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>E-mail</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="42"/>
<source>Comment</source>
- <translation type="unfinished"></translation>
+ <translation>Commenter</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="55"/>
<source>Create New UID</source>
- <translation type="unfinished"></translation>
+ <translation>Créer de nouveaux uid</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="68"/>
<source> Name must contain at least five characters.
</source>
- <translation type="unfinished"></translation>
+ <translation>Le nom doit contenir au moins cinq caractères.</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="70"/>
<source> Please give a email address.
</source>
- <translation type="unfinished"></translation>
+ <translation>S&apos;il vous plaît donner une adresse email.</translation>
</message>
</context>
<context>
<name>KeyPairDetailTab</name>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
<source>Owner</source>
- <translation type="unfinished"></translation>
+ <translation>Propriétaire</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
<source>Master Key</source>
- <translation type="unfinished"></translation>
+ <translation>La clef maitresse</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/>
<source>Fingerprint</source>
- <translation type="unfinished"></translation>
+ <translation>Empreinte digitale</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/>
<source>Additional UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>UID supplémentaires</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Exists</source>
+ <translation>Existe</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Not Exists</source>
+ <translation>N&apos;existe pas</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
<source>Name:</source>
- <translation type="unfinished"></translation>
+ <translation>Nom:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/>
<source>Email Address:</source>
- <translation type="unfinished"></translation>
+ <translation>Adresse e-mail:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/>
<source>Comment:</source>
- <translation type="unfinished"></translation>
+ <translation>Commenter:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
<source>Key ID: </source>
- <translation type="unfinished"></translation>
+ <translation>ID de clé:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
<source>Algorithm: </source>
- <translation type="unfinished"></translation>
+ <translation>Algorithme:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
<source>Key Size:</source>
- <translation type="unfinished"></translation>
+ <translation>Taille de la clé:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
<source>Nominal Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>Utilisation nominale:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
<source>Actual Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>Utilisation réelle:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
<source>Expires on: </source>
- <translation type="unfinished"></translation>
+ <translation>Expire le:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/>
<source>Last Update: </source>
- <translation type="unfinished"></translation>
+ <translation>Dernière mise à jour:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/>
<source>Secret Key Existence: </source>
- <translation type="unfinished"></translation>
+ <translation>Existence de clé secrète:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
<source>Copy</source>
- <translation type="unfinished"></translation>
+ <translation>Copie</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/>
<source>copy fingerprint to clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Copier l&apos;empreinte digitale dans le presse-papier</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/>
<source>Operations</source>
- <translation type="unfinished"></translation>
+ <translation>Exploitation</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/>
- <source>Export Private Key (Include Subkeys)</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/>
+ <source>Export Private Key (Include Subkey)</source>
+ <translation>Exporter une clé privée (inclure la sous-clé)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/>
<source>Modify Expiration Datetime (Master Key)</source>
- <translation type="unfinished"></translation>
+ <translation>Modifier l&apos;expiration DateTime (clé principale)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/>
<source>Key Server Operation (Pubkey)</source>
- <translation type="unfinished"></translation>
+ <translation>Fonctionnement du serveur clé (Pubkey)</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/>
+ <source>Generate Revoke Certificate</source>
+ <translation>Générer un certificat de révocation</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/>
<source>Warning: The Master Key has expired.</source>
- <translation type="unfinished"></translation>
+ <translation>AVERTISSEMENT: la clé principale a expiré.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/>
<source>Warning: The Master Key has been revoked</source>
- <translation type="unfinished"></translation>
+ <translation>AVERTISSEMENT: la clé principale a été révoquée</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/>
<source>Exporting private Key</source>
- <translation type="unfinished"></translation>
+ <translation>Exportation de la clé privée</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/>
- <source>&lt;h3&gt;You are about to export your &lt;font color=&quot;red&quot;&gt;PRIVATE KEY&lt;/font&gt;!&lt;/h3&gt;
-This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALLY want to export your PRIVATE KEY?</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/>
+ <source>You are about to export your</source>
+ <translation>Vous êtes sur le point d&apos;exporter votre</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/>
+ <source>PRIVATE KEY</source>
+ <translation>CLÉ PRIVÉE</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/>
+ <source>This is NOT your Public Key, so DON&apos;T give it away.</source>
+ <translation>Ce n&apos;est pas votre clé publique, alors ne le donnez pas.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/>
+ <source>Do you REALLY want to export your PRIVATE KEY?</source>
+ <translation>Voulez-vous vraiment exporter votre clé privée?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/>
<source>Export Key To File</source>
- <translation type="unfinished"></translation>
+ <translation>Exporter la clé pour déposer</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/>
<source>Key Files</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers clés</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Export Error</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur d&apos;exportation</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Couldn&apos;t open %1 for writing</source>
- <translation type="unfinished"></translation>
+ <translation>Ne pouvait pas ouvrir% 1 pour écrire</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>N&apos;expire jamais</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/>
- <source>Upload Key Pair</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/>
+ <source>Upload Key Pair to Key Server</source>
+ <translation>Télécharger la paire de touches sur le serveur de clés</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/>
<source>Update Key Pair</source>
- <translation type="unfinished"></translation>
+ <translation>Mettre à jour la paire de clés</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/>
+ <source>Generate revocation certificate</source>
+ <translation>Générer un certificat de révocation</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/>
+ <source>Revocation Certificates</source>
+ <translation>Certificats de révocation</translation>
</message>
</context>
<context>
@@ -1417,87 +1489,87 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="37"/>
<source>Generate A New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Générer une nouvelle sous-clé</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
<source>Key ID: </source>
- <translation type="unfinished"></translation>
+ <translation>ID de clé:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
<source>Algorithm: </source>
- <translation type="unfinished"></translation>
+ <translation>Algorithme:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
<source>Key Size:</source>
- <translation type="unfinished"></translation>
+ <translation>Taille de la clé:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
<source>Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>Usage:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
<source>Expires On </source>
- <translation type="unfinished"></translation>
+ <translation>Expire le</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
<source>Last Update: </source>
- <translation type="unfinished"></translation>
+ <translation>Dernière mise à jour:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
<source>Existence: </source>
- <translation type="unfinished"></translation>
+ <translation>Existence:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/>
<source>Fingerprint: </source>
- <translation type="unfinished"></translation>
+ <translation>Empreinte digitale:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Subkey ID</source>
- <translation type="unfinished"></translation>
+ <translation>Adresse de sous-clé</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Key Size</source>
- <translation type="unfinished"></translation>
+ <translation>Taille de clé</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Algo</source>
- <translation type="unfinished"></translation>
+ <translation>Quelque chose</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Create Date</source>
- <translation type="unfinished"></translation>
+ <translation>créer un rendez-vous</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>Date d&apos;expiration</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>N&apos;expire jamais</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/>
<source>Never Expires</source>
- <translation type="unfinished"></translation>
+ <translation>N&apos;expire jamais</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/>
<source>Edit Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>Modifier la date d&apos;expire</translation>
</message>
</context>
<context>
@@ -1505,192 +1577,202 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="39"/>
<source>New UID</source>
- <translation type="unfinished"></translation>
+ <translation>Nouveau UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="40"/>
<source>UID Management</source>
- <translation type="unfinished"></translation>
+ <translation>Gestion UID</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/>
+ <source>UIDs</source>
+ <translation>Uids</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/>
+ <source>Signature of Selected UID</source>
+ <translation>Signature de l&apos;UID sélectionné</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Select</source>
- <translation type="unfinished"></translation>
+ <translation>Sélectionner</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>Nom</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>E-mail</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Comment</source>
- <translation type="unfinished"></translation>
+ <translation>Commenter</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Key ID</source>
- <translation type="unfinished"></translation>
+ <translation>Identifiant de clé</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Create Date</source>
- <translation type="unfinished"></translation>
+ <translation>créer un rendez-vous</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Expired Date</source>
- <translation type="unfinished"></translation>
+ <translation>Date d&apos;expiration</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/>
<source>Never Expires</source>
- <translation type="unfinished"></translation>
+ <translation>N&apos;expire jamais</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Opération invalide</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/>
<source>Please select one or more UIDs before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Veuillez sélectionner un ou plusieurs UID avant de faire cette opération.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/>
<source>Sign Selected UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Signer des UID sélectionnés</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/>
<source>Delete Selected UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer l&apos;UID sélectionné (s) sélectionné (s)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/>
<source>Successful Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Exploitation réussie</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
<source>Successfully added a new UID.</source>
- <translation type="unfinished"></translation>
+ <translation>A ajouté avec succès une nouvelle UID.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/>
<source>Operation Failed</source>
- <translation type="unfinished"></translation>
+ <translation>L&apos;opération a échoué</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/>
<source>An error occurred during the operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Une erreur s&apos;est produite lors de l&apos;opération.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/>
<source>Deleting UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>Suppression des UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/>
<source>Are you sure that you want to delete the following uids?</source>
- <translation type="unfinished"></translation>
+ <translation>Êtes-vous sûr de vouloir supprimer les UID suivants?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/>
<source>The action can not be undone.</source>
- <translation type="unfinished"></translation>
+ <translation>L&apos;action ne peut pas être annulée.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/>
<source>Set Primary UID</source>
- <translation type="unfinished"></translation>
+ <translation>Définir UID primaire</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/>
<source>Are you sure that you want to set the Primary UID to?</source>
- <translation type="unfinished"></translation>
+ <translation>Êtes-vous sûr de vouloir définir l&apos;UID principal?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/>
<source>Set As Primary</source>
- <translation type="unfinished"></translation>
+ <translation>Définir comme principale</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/>
<source>Sign UID</source>
- <translation type="unfinished"></translation>
+ <translation>Signer uid</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/>
<source>Delete UID</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/>
<source>Please select one UID before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Veuillez sélectionner un UID avant de faire cette opération.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/>
<source>Deleting UID</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/>
<source>Are you sure that you want to delete the following uid?</source>
- <translation type="unfinished"></translation>
+ <translation>Êtes-vous sûr de vouloir supprimer l&apos;UID suivant?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/>
<source>Delete(Revoke) Key Signature</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer (révoquer) la signature de clé</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/>
<source>Please select one Key Signature before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Veuillez sélectionner une signature de clé avant de faire cette opération.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/>
<source>To delete the signature, you need to have its corresponding public key in the local database.</source>
- <translation type="unfinished"></translation>
+ <translation>Pour supprimer la signature, vous devez avoir sa clé publique correspondante dans la base de données locale.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/>
<source>Deleting Key Signature</source>
- <translation type="unfinished"></translation>
+ <translation>Suppression de la signature de clé</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/>
<source>Are you sure that you want to delete the following signature?</source>
- <translation type="unfinished"></translation>
+ <translation>Êtes-vous sûr de vouloir supprimer la signature suivante?</translation>
</message>
</context>
<context>
@@ -1698,110 +1780,110 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="40"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Fermer</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="41"/>
<source>&amp;Import ALL</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Importer tout</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="42"/>
<source>&amp;Search</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Rechercher</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="45"/>
<source>Search String:</source>
- <translation type="unfinished"></translation>
+ <translation>String de recherche:</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="49"/>
<source>Key Server:</source>
- <translation type="unfinished"></translation>
+ <translation>Serveur clé:</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="97"/>
<source>Update Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Mettre à jour les clés de Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="99"/>
<source>Import Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Keys d&apos;importation de KeyServer</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>UID</source>
- <translation type="unfinished"></translation>
+ <translation>Uid</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>Creation date</source>
- <translation type="unfinished"></translation>
+ <translation>Date de création</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>KeyID</source>
- <translation type="unfinished"></translation>
+ <translation>Clés</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>Tag</source>
- <translation type="unfinished"></translation>
+ <translation>Étiqueter</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/>
- <source>&lt;h4&gt;Text is empty.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Text is empty.</source>
+ <translation>Le texte est vide.</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/>
<source>Not Key Found</source>
- <translation type="unfinished"></translation>
+ <translation>Pas la clé trouvée</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/>
<source>Timeout</source>
- <translation type="unfinished"></translation>
+ <translation>Temps libre</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/>
<source>Key Server Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>Server clé non trouvé</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/>
<source>Connection Error</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur de connexion</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/>
- <source>&lt;h4&gt;CToo many responses from keyserver!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Too many responses from keyserver!</source>
+ <translation>Trop de réponses de KeyServer!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/>
- <source>&lt;h4&gt;No keys found, input may be kexId, retrying search with 0x.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>No keys found, input may be kexId, retrying search with 0x.</source>
+ <translation>Aucune clé trouvée, l&apos;entrée peut être Kexid, réessayant la recherche avec 0x.</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/>
- <source>&lt;h4&gt;No keys found containing the search string!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>No keys found containing the search string!</source>
+ <translation>Aucun clés trouvée contenant la chaîne de recherche!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/>
- <source>&lt;h4&gt;Insufficiently specific search string!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Insufficiently specific search string!</source>
+ <translation>String de recherche insuffisamment spécifique!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="274"/>
<source>revoked</source>
- <translation type="unfinished"></translation>
+ <translation>révoqué</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="277"/>
@@ -1811,27 +1893,27 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="317"/>
<source>&lt;h4&gt;%1 keys found. Double click a key to import it.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;H4&gt;% 1 clés trouvées.Double-cliquez sur une touche pour importer. &lt;/ H4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="383"/>
<source>Key Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>Clé introuvable</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="410"/>
<source>&lt;h4&gt;Key Updated&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;H4&gt; Touche Mise à jour &lt;/ h4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="412"/>
<source>&lt;h4&gt;Key Imported&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;H4&gt; Touche importée &lt;/ h4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="473"/>
<source>Upload Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Touches de téléchargement de KeyServer</translation>
</message>
</context>
<context>
@@ -1839,22 +1921,22 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="36"/>
<source>Confirm</source>
- <translation type="unfinished"></translation>
+ <translation>Confirmer</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="41"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>N&apos;expire jamais</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="61"/>
<source>Operation Failed</source>
- <translation type="unfinished"></translation>
+ <translation>L&apos;opération a échoué</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="62"/>
<source>An error occurred during the operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Une erreur s&apos;est produite lors de l&apos;opération.</translation>
</message>
</context>
<context>
@@ -1862,263 +1944,351 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="72"/>
<source>Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>Date d&apos;expiration</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="81"/>
<source>Sign For Key&apos;s UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Signe pour UID (s) de la clé</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="100"/>
<source>Unsuccessful Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Opération infructueuse</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="101"/>
<source>Signature operation failed for UID </source>
- <translation type="unfinished"></translation>
+ <translation>L&apos;opération de signature a échoué pour UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="108"/>
<source>Operation Complete</source>
- <translation type="unfinished"></translation>
+ <translation>Opération complète</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="109"/>
<source>The signature operation of the UID is complete</source>
- <translation type="unfinished"></translation>
+ <translation>L&apos;opération de signature de l&apos;UID est complète</translation>
</message>
</context>
<context>
<name>KeyUploadDialog</name>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/>
<source>Uploading Public Key</source>
- <translation type="unfinished"></translation>
+ <translation>Téléchargement de clé publique</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/>
<source>Key Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>Clé introuvable</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/>
<source>Timeout</source>
- <translation type="unfinished"></translation>
+ <translation>Temps libre</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/>
<source>Key Server Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>Server clé non trouvé</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/>
<source>Connection Error</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur de connexion</translation>
</message>
</context>
<context>
<name>KeyserverTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="508"/>
- <source>Default Keyserver for import:</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="607"/>
+ <source>Default Key Server for import:</source>
+ <translation>Server de clé par défaut pour importer:</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="525"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="624"/>
<source>Add</source>
- <translation type="unfinished"></translation>
+ <translation>Ajouter</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/>
+ <location filename="../../src/MainWindow.cpp" line="35"/>
+ <source>Loading Gnupg</source>
+ <translation>Chargement gnupg</translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="62"/>
+ <source>ENV Loading Failed</source>
+ <translation>Échec du chargement env</translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="63"/>
+ <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
+ <translation>GNUPG n&apos;est pas installé correctement, veuillez suivre les instructions README pour installer GNUPG, puis ouvrir GPGFontend.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/>
<source>No Key Selected</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune clé sélectionnée</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Opération invalide</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/>
<source>The selected key contains a key that does not actually have a encrypt usage.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>La clé sélectionnée contient une clé qui ne dispose pas d&apos;une utilisation en chiffrement. &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/>
+ <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
+ <translation>&lt;br/&gt; Par exemple, la clé suivante: &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/>
+ <source>Encrypting</source>
+ <translation>Cryptage</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/>
+ <source>Function Disabled</source>
+ <translation>Fonction désactivée</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/>
+ <source>Please go to the settings interface to enable and configure this function.</source>
+ <translation>Veuillez vous rendre à l&apos;interface des paramètres pour activer et configurer cette fonction.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/>
<source>The selected key contains a key that does not actually have a signature usage.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>La clé sélectionnée contient une clé qui ne dispose pas d&apos;une utilisation de signature. &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/>
+ <source>Signing</source>
+ <translation>Signature</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/>
+ <source>Decrypting</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/>
+ <source>Verifying</source>
+ <translation>Vérification</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/>
<source>Invalid KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>KeyPair non valide</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/>
<source>The selected keypair cannot be used for signing and encryption at the same time.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Le clavier sélectionné ne peut pas être utilisé pour la signature et le cryptage en même temps. &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/>
<source>Incomplete Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Opération incomplète</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/>
<source>None of the selected key pairs can provide the encryption function.</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune des paires de touches sélectionnées ne peut fournir la fonction de cryptage.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/>
<source>None of the selected key pairs can provide the signature function.</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune des paires de touches sélectionnées ne peut fournir la fonction de signature.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/>
+ <source>Encrypting and Signing</source>
+ <translation>Cryptage et signature</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/>
+ <source>Decrypting and Verifying</source>
+ <translation>Décrypter et vérifier</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>Error</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <source>Select a file before doing it.</source>
+ <translation>Sélectionnez un fichier avant de le faire.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
<source>No permission to read this file.</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune autorisation de lire ce fichier.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
<source>No permission to create file.</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune autorisation de créer un fichier.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>Avertissement</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/>
<source>The target file already exists, do you need to overwrite it?</source>
- <translation type="unfinished"></translation>
+ <translation>Le fichier cible existe déjà, devez-vous vous écraser?</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>An error occurred during operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Une erreur s&apos;est produite lors du fonctionnement.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/>
<source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source>
- <translation type="unfinished"></translation>
+ <translation>Veuillez sélectionner le fichier cible ou le fichier de signature approprié.Assurez-vous que les deux sont dans ce répertoire.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
<source>No permission to read target file.</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune autorisation de lire le fichier cible.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
<source>No permission to read signature file.</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune autorisation de lire le fichier de signature.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
<source>Select a file(.gpg/.asc) before doing it.</source>
- <translation type="unfinished"></translation>
+ <translation>Sélectionnez un fichier (.gpg / .asc) avant de le faire.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/>
- <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/>
+ <source>Outdated Version</source>
+ <translation>Version obsolète</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
- <source>Select a file before doing it.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/>
+ <source>This version(%1) is out of date, please update the latest version in time. </source>
+ <translation>Cette version (% 1) est obsolète, veuillez mettre à jour la dernière version à temps.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/>
+ <source>You can download the latest version(%1) on Github Releases Page.&lt;br/&gt;</source>
+ <translation>Vous pouvez télécharger la dernière version (% 1) sur la page Communiqués GitHub. &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/>
+ <source>Unreleased Version</source>
+ <translation>Version non sélectionnée</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/>
+ <source>This version(%1) has not been officially released and is not recommended for use in a production environment. &lt;br/&gt;</source>
+ <translation>Cette version (% 1) n&apos;a pas été officiellement libérée et n&apos;est pas recommandée pour une utilisation dans un environnement de production.&lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/>
<source>There is one unencrypted file in attachment folder</source>
- <translation type="unfinished"></translation>
+ <translation>Il y a un fichier non crypté dans le dossier de pièce jointe</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source>There are </source>
- <translation type="unfinished"></translation>
+ <translation>Il y a</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source> unencrypted files in attachment folder</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers non cryptés dans le dossier de pièce jointe</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="30"/>
@@ -2128,7 +2298,7 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="36"/>
<source>Open a new file</source>
- <translation type="unfinished"></translation>
+ <translation>Ouvrir un nouveau fichier</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="39"/>
@@ -2138,277 +2308,277 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="42"/>
<source>Open an existing file</source>
- <translation type="unfinished"></translation>
+ <translation>Ouvrir un fichier existant</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="45"/>
<source>&amp;Browser</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Le navigateur</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="47"/>
<source>Open a file browser</source>
- <translation type="unfinished"></translation>
+ <translation>Ouvrez un navigateur de fichiers</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="50"/>
<source>&amp;Save</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Sauvegarder</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="53"/>
<source>Save the current File</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrez le fichier actuel</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="56"/>
<source>Save &amp;As</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer sous</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="59"/>
<source>Save the current File as...</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrez le fichier actuel comme ...</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="62"/>
<source>&amp;Print</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Imprimer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="65"/>
<source>Print Document</source>
- <translation type="unfinished"></translation>
+ <translation>Document d&apos;impression</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="68"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Fermer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="70"/>
<source>Close file</source>
- <translation type="unfinished"></translation>
+ <translation>Fermer le fichier</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="73"/>
<source>&amp;Quit</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Quitter</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="76"/>
<source>Quit Program</source>
- <translation type="unfinished"></translation>
+ <translation>Quitter le programme</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="81"/>
<source>&amp;Undo</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Annuler</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="83"/>
<source>Undo Last Edit Action</source>
- <translation type="unfinished"></translation>
+ <translation>Annuler la dernière action d&apos;édition</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="86"/>
<source>&amp;Redo</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Prêt</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="88"/>
<source>Redo Last Edit Action</source>
- <translation type="unfinished"></translation>
+ <translation>Refaire dernière action d&apos;édition</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="91"/>
<source>Zoom In</source>
- <translation type="unfinished"></translation>
+ <translation>Agrandir</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="95"/>
<source>Zoom Out</source>
- <translation type="unfinished"></translation>
+ <translation>Dézoomer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="99"/>
<source>&amp;Paste</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Pâte</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="102"/>
<source>Paste Text From Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Coller le texte du presse-papiers</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="105"/>
<source>Cu&amp;t</source>
- <translation type="unfinished"></translation>
+ <translation>Avec &amp; T.</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="108"/>
<source>Cut the current selection&apos;s contents to the clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Couper le contenu de la sélection actuelle dans le presse-papiers</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="112"/>
<source>&amp;Copy</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Copie</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="115"/>
<source>Copy the current selection&apos;s contents to the clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Copiez le contenu de la sélection actuelle dans le Presse-papiers</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="119"/>
<source>&amp;Quote</source>
- <translation type="unfinished"></translation>
+ <translation>&quot;</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="121"/>
<source>Quote whole text</source>
- <translation type="unfinished"></translation>
+ <translation>Citer du texte entier</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="124"/>
<source>Select &amp;All</source>
- <translation type="unfinished"></translation>
+ <translation>Tout sélectionner</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="127"/>
<source>Select the whole text</source>
- <translation type="unfinished"></translation>
+ <translation>Sélectionnez le texte entier</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="130"/>
<source>&amp;Find</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Trouve</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="132"/>
<source>Find a word</source>
- <translation type="unfinished"></translation>
+ <translation>Trouver un mot</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="135"/>
<source>Remove &amp;spacing</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer et espacer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="138"/>
<source>Remove double linebreaks, e.g. in pasted text from webmailer</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer Double Ligneurs, par exemple.dans le texte collé de webmailer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="141"/>
<source>Se&amp;ttings</source>
- <translation type="unfinished"></translation>
+ <translation>Et tuttine</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="142"/>
<source>Open settings dialog</source>
- <translation type="unfinished"></translation>
+ <translation>Dialogue des paramètres ouverts</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="148"/>
<source>&amp;Encrypt</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Crypter</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="151"/>
<source>Encrypt Message</source>
- <translation type="unfinished"></translation>
+ <translation>Chiffrer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="154"/>
<source>&amp;Encrypt &amp;Sign</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Chiffrer et signer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="157"/>
<source>Encrypt and Sign Message</source>
- <translation type="unfinished"></translation>
+ <translation>Message de chiffrement et de signe</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="160"/>
<source>&amp;Decrypt</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Déchiffrer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="163"/>
<source>Decrypt Message</source>
- <translation type="unfinished"></translation>
+ <translation>Decrypt Message</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="166"/>
<source>&amp;Decrypt &amp;Verify</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Déchiffrer et vérifier</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="169"/>
<source>Decrypt and Verify Message</source>
- <translation type="unfinished"></translation>
+ <translation>Déchiffrer et vérifier le message</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="175"/>
<source>&amp;Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Chiffrer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="176"/>
<source>Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Chiffrer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="179"/>
<source>&amp;Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Dossier de déchiffrement</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="180"/>
<source>Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Dossier de déchiffrement</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="183"/>
<source>&amp;Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>Et signe de signe</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="184"/>
<source>Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>Fichier de signe</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="187"/>
<source>&amp;Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>Vérifier le fichier</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="188"/>
<source>Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>Vérifier le fichier</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="192"/>
<source>&amp;Sign</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Signe</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="195"/>
<source>Sign Message</source>
- <translation type="unfinished"></translation>
+ <translation>Message de signe</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="198"/>
<source>&amp;Verify</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Vérifier</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="201"/>
<source>Verify Message</source>
- <translation type="unfinished"></translation>
+ <translation>Vérifier le message</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="207"/>
@@ -2418,245 +2588,212 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="209"/>
<source>Import New Key From Editor</source>
- <translation type="unfinished"></translation>
+ <translation>Importer une nouvelle clé de l&apos;éditeur</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/>
- <source>Manage &amp;keys</source>
- <translation type="unfinished"></translation>
+ <source>Manage &amp;Keys</source>
+ <translation>Gérer et les clés</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="214"/>
<source>Open Keymanagement</source>
- <translation type="unfinished"></translation>
+ <translation>Clés ouverte</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/>
<source>&amp;About</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;À propos</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/>
<source>Show the application&apos;s About box</source>
- <translation type="unfinished"></translation>
+ <translation>Montrer l&apos;application à propos de la boîte</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/>
+ <source>&amp;Check for Updates</source>
+ <translation>Vérifier les mises à jour</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <source>Check for updates</source>
+ <translation>Vérifier les mises à jour</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/>
<source>Open &amp;Wizard</source>
- <translation type="unfinished"></translation>
+ <translation>Open &amp; Wizard</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
<source>Open the wizard</source>
- <translation type="unfinished"></translation>
+ <translation>Ouvrir l&apos;assistant</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
<source>Append Selected Key(s) To Text</source>
- <translation type="unfinished"></translation>
+ <translation>Ajoutez la ou les touches sélectionnées sur le texte</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
<source>Append The Selected Keys To Text in Editor</source>
- <translation type="unfinished"></translation>
+ <translation>Ajouter les touches sélectionnées sur Text In Editor</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
- <source>Copy EMail-address</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <source>Copy Email</source>
+ <translation>Copier le courrier électronique</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/>
- <source>Copy selected EMailaddress to clipboard</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <source>Copy selected Email to clipboard</source>
+ <translation>Copier le courrier électronique sélectionné dans le presse-papiers</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
<source>Show Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>Afficher les détails de la clé</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/>
<source>Show Details for this Key</source>
- <translation type="unfinished"></translation>
+ <translation>Afficher les détails de cette clé</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/>
<source>Refresh Key From Key Server</source>
- <translation type="unfinished"></translation>
+ <translation>Actualiser la clé de Key Server</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/>
<source>Refresh key from default key server</source>
- <translation type="unfinished"></translation>
+ <translation>Actualiser la clé à partir du serveur de clés par défaut</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/>
<source>Upload Public Key(s) To Server</source>
- <translation type="unfinished"></translation>
+ <translation>Télécharger des touches publiques sur le serveur</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/>
<source>Upload The Selected Public Keys To Server</source>
- <translation type="unfinished"></translation>
+ <translation>Téléchargez les touches publiques sélectionnées sur le serveur</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/>
<source>Remove PGP Header</source>
- <translation type="unfinished"></translation>
+ <translation>Supprimer l&apos;en-tête PGP</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/>
<source>Add PGP Header</source>
- <translation type="unfinished"></translation>
+ <translation>Ajouter l&apos;en-tête PGP</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/>
<source>&amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Déposer</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/>
<source>&amp;Edit</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Éditer</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/>
<source>&amp;File...</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Déposer...</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/>
<source>&amp;Crypt</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Crypte</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
<source>&amp;Keys</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Clés</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/>
<source>&amp;Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>Clé d&apos;importation</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/>
<source>&amp;Steganography</source>
- <translation type="unfinished"></translation>
+ <translation>Stéganographie</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
<source>&amp;View</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Vue</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/>
<source>&amp;Help</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Aider</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/>
<source>File</source>
- <translation type="unfinished"></translation>
+ <translation>Déposer</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/>
<source>Crypt</source>
- <translation type="unfinished"></translation>
+ <translation>Crypte</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/>
<source>Key</source>
- <translation type="unfinished"></translation>
+ <translation>Clé</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/>
<source>Edit</source>
- <translation type="unfinished"></translation>
+ <translation>Éditer</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/>
<source>Special Edit</source>
- <translation type="unfinished"></translation>
+ <translation>Édition spéciale</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/>
<source>Import key from...</source>
- <translation type="unfinished"></translation>
+ <translation>Importer la clé de ...</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/>
<source>Import key</source>
- <translation type="unfinished"></translation>
+ <translation>Clé d&apos;importation</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/>
<source>Browser to view and operate file</source>
- <translation type="unfinished"></translation>
+ <translation>Navigateur pour voir et utiliser le fichier</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/>
<source>Browser</source>
- <translation type="unfinished"></translation>
+ <translation>Le navigateur</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/>
<source>Ready</source>
- <translation type="unfinished"></translation>
+ <translation>Prêt</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/>
<source>Key ToolBox</source>
- <translation type="unfinished"></translation>
+ <translation>Boîte à outils clé</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/>
<source>Information Board</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/>
- <source>Attached files:</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>MimeTab</name>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
- <source>Decode quoted printable</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="292"/>
- <source>Try to recognize quoted printable.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="296"/>
- <source>Parse PGP/MIME (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="299"/>
- <source>Try to split attachments from PGP-MIME ecrypted messages.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="304"/>
- <source>Open with external application (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="306"/>
- <source>Open attachments with default application for the filetype.&lt;br&gt; There are at least two possible problems with this behaviour:&lt;ol&gt;&lt;li&gt;File needs to be saved unencrypted to attachments folder.&lt;br&gt; Its your job to clean this folder.&lt;/li&gt;&lt;li&gt;The external application may have its own temp files.&lt;/li&gt;&lt;/ol&gt;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
- <source>Enable opening with external applications.</source>
- <translation type="unfinished"></translation>
+ <translation>Tableau d&apos;information</translation>
</message>
</context>
<context>
@@ -2664,12 +2801,12 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/gpg/result_analyse/DecryptResultAnalyse.cpp" line="42"/>
<source>&gt;Recipient: </source>
- <translation type="unfinished"></translation>
+ <translation>&gt; Destinataire:</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="35"/>
<source>One or More Bad Signatures.</source>
- <translation type="unfinished"></translation>
+ <translation>Une ou plusieurs mauvaises signatures.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="40"/>
@@ -2679,92 +2816,92 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="42"/>
<source>Good </source>
- <translation type="unfinished"></translation>
+ <translation>Bien</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="45"/>
<source>Bad </source>
- <translation type="unfinished"></translation>
+ <translation>Mal</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="48"/>
<source>Expired </source>
- <translation type="unfinished"></translation>
+ <translation>Expiré</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="51"/>
<source>Missing Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>Touches manquantes</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="54"/>
<source>Revoked Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>Touche révoquée</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="57"/>
<source>Expired Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>Clé expirée</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="60"/>
<source>Missing CRL&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>CRL manquant</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="64"/>
<source>Signature Fully Valid.</source>
- <translation type="unfinished"></translation>
+ <translation>Signature entièrement valide.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="66"/>
<source>Signature NOT Fully Valid.</source>
- <translation type="unfinished"></translation>
+ <translation>Signature non complète valide.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="74"/>
<source>Key is NOT present with ID 0x</source>
- <translation type="unfinished"></translation>
+ <translation>La clé n&apos;est pas présente avec ID 0x</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="81"/>
<source>A signature could NOT be verified due to a Missing Key
</source>
- <translation type="unfinished"></translation>
+ <translation>Une signature n&apos;a pas pu être vérifiée en raison d&apos;une clé manquante</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="85"/>
<source>A signature is valid but the key used to verify the signature has been revoked
</source>
- <translation type="unfinished"></translation>
+ <translation>Une signature est valide mais la clé utilisée pour vérifier la signature a été révoquée.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="93"/>
<source>A signature is valid but expired
</source>
- <translation type="unfinished"></translation>
+ <translation>Une signature est valide mais expirée</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="100"/>
<source>A signature is valid but the key used to verify the signature has expired.
</source>
- <translation type="unfinished"></translation>
+ <translation>Une signature est valide mais la clé utilisée pour vérifier la signature a expiré.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="107"/>
<source>There was some other error which prevented the signature verification.
</source>
- <translation type="unfinished"></translation>
+ <translation>Il y avait une autre erreur qui empêchait la vérification de la signature.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="113"/>
<source>Error for key with fingerprint </source>
- <translation type="unfinished"></translation>
+ <translation>Erreur pour la clé avec empreinte digitale</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="128"/>
<source>Signed By: </source>
- <translation type="unfinished"></translation>
+ <translation>Signé par:</translation>
</message>
</context>
<context>
@@ -2772,60 +2909,193 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="29"/>
<source>Unsaved Files</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers non enregistrés</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="77"/>
- <source>&lt;h3&gt;%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?&lt;/h3&gt;</source>
- <translation type="unfinished"></translation>
+ <source>%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?</source>
+ <translation>% 1 Les fichiers contiennent des informations non enregistrées. &lt;br/&gt; Enregistrez les modifications avant la fermeture?</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="88"/>
<source>Check the files you want to save:</source>
- <translation type="unfinished"></translation>
+ <translation>Vérifiez les fichiers que vous souhaitez enregistrer:</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="89"/>
<source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;B&gt; REMARQUE: &lt;/ B&gt; Si vous ne enregistrez pas ces fichiers, toutes les modifications sont perdues. &lt;br/&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>SendMailDialog</name>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="35"/>
+ <source>Incomplete configuration</source>
+ <translation>Configuration incomplète</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="36"/>
+ <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source>
+ <translation>L&apos;adresse SMTP est vide, veuillez vous rendre à l&apos;interface de réglage pour compléter la configuration.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="86"/>
+ <source> Recipient cannot be empty
+</source>
+ <translation>Le destinataire ne peut pas être vide</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="91"/>
+ <source> One or more Recipient&apos;s Email Address is invalid
+</source>
+ <translation>L&apos;une ou plusieurs adresse électronique du destinataire est invalide</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="97"/>
+ <source> Sender cannot be empty
+</source>
+ <translation>L&apos;expéditeur ne peut pas être vide</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="99"/>
+ <source> Sender&apos;s Email Address is invalid
+</source>
+ <translation>L&apos;adresse email de l&apos;expéditeur n&apos;est pas valide</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail</source>
+ <translation>Échouer</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation>Omettre de connecter SMTP Server</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <source>Fail to Login into SMTP Server</source>
+ <translation>Omettre de vous connecter au serveur SMTP</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail to Send Mail to SMTP Server</source>
+ <translation>Omettre d&apos;envoyer un courrier au serveur SMTP</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Success</source>
+ <translation>Succès</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Succeed in Sending Mail to SMTP Server</source>
+ <translation>Réussir à envoyer un courrier au serveur SMTP</translation>
+ </message>
+</context>
+<context>
+ <name>SendMailTab</name>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
+ <source>Enable</source>
+ <translation>Activer</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="311"/>
+ <source>SMTP Address</source>
+ <translation>Adresse SMTP</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="313"/>
+ <source>Username</source>
+ <translation>Nom d&apos;utilisateur</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
+ <source>Password</source>
+ <translation>Mot de passe</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="317"/>
+ <source>Port</source>
+ <translation>Port</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="319"/>
+ <source>Connection Security</source>
+ <translation>Sécurité de la connexion</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="322"/>
+ <source>Default Sender</source>
+ <translation>Expéditeur par défaut</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail</source>
+ <translation>Échouer</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation>Omettre de connecter SMTP Server</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail to Login</source>
+ <translation>Échouer à se connecter</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Success</source>
+ <translation>Succès</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Succeed in connecting and login</source>
+ <translation>Réussir à connecter et à vous connecter</translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="38"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
<source>General</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="39"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
<source>Appearance</source>
- <translation type="unfinished"></translation>
+ <translation>Apparence</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
- <source>PGP/Mime</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="42"/>
+ <source>Send Mail</source>
+ <translation>Envoyer un mail</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
<source>Key Server</source>
- <translation type="unfinished"></translation>
+ <translation>Serveur de clés</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="45"/>
<source>Advanced</source>
- <translation type="unfinished"></translation>
+ <translation>Avancée</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="56"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="58"/>
<source>Settings</source>
- <translation type="unfinished"></translation>
+ <translation>Paramètres</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="101"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="103"/>
<source>System Default</source>
- <translation type="unfinished"></translation>
+ <translation>Défaut du système</translation>
</message>
</context>
<context>
@@ -2833,62 +3103,62 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="46"/>
<source>Generate New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Générer une nouvelle sous-clé</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="61"/>
<source>Encryption</source>
- <translation type="unfinished"></translation>
+ <translation>Chiffrement</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="64"/>
<source>Signing</source>
- <translation type="unfinished"></translation>
+ <translation>Signature</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="67"/>
<source>Certification</source>
- <translation type="unfinished"></translation>
+ <translation>Certification</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="70"/>
<source>Authentication</source>
- <translation type="unfinished"></translation>
+ <translation>Authentification</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="114"/>
<source>Expiration Date:</source>
- <translation type="unfinished"></translation>
+ <translation>Date d&apos;expiration:</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="115"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>N&apos;expire jamais</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="116"/>
<source>KeySize (in Bit):</source>
- <translation type="unfinished"></translation>
+ <translation>Keysize (dans le bit):</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="117"/>
<source>Key Type:</source>
- <translation type="unfinished"></translation>
+ <translation>Type de clé:</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="126"/>
<source>Basic Information</source>
- <translation type="unfinished"></translation>
+ <translation>Informations de base</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="214"/>
<source> Expiration time no more than 2 years. </source>
- <translation type="unfinished"></translation>
+ <translation>Heure d&apos;expiration Pas plus de 2 ans.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="235"/>
<source>Generating Subkey...</source>
- <translation type="unfinished"></translation>
+ <translation>Génération de sous-clé ...</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="238"/>
@@ -2896,90 +3166,129 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
This may take a while.
To speed up the process use your computer
(e.g. browse the net, listen to music,...)</source>
- <translation type="unfinished"></translation>
+ <translation>Collecte de données aléatoires pour la génération de sous-clé.
+ Cela peut prendre un peu de temps.
+ Pour accélérer le processus, utilisez votre ordinateur
+ (E.G. Parcourir le Net, écoutez de la musique, ...)</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/>
<source>Success</source>
- <translation type="unfinished"></translation>
+ <translation>Succès</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/>
<source>The new subkey has been generated.</source>
- <translation type="unfinished"></translation>
+ <translation>La nouvelle sous-clé a été générée.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/>
<source>Failure</source>
- <translation type="unfinished"></translation>
+ <translation>Échec</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/>
<source>An error occurred during subkey generation.</source>
- <translation type="unfinished"></translation>
+ <translation>Une erreur s&apos;est produite lors de la génération de sous-clé.</translation>
</message>
</context>
<context>
<name>TextEdit</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/>
<source>untitled</source>
- <translation type="unfinished"></translation>
+ <translation>sans titre</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>Avertissement</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/>
+ <source>Cannot read file %1:
+%2.</source>
+ <translation>Impossible de lire le fichier% 1:
+% 2.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/>
<source>Open file</source>
- <translation type="unfinished"></translation>
+ <translation>Fichier ouvert</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/>
+ <source>File</source>
+ <translation>Déposer</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/>
+ <source>Cannot write file %1:
+%2.</source>
+ <translation>Impossible d&apos;écrire le fichier% 1:
+% 2.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
<source>Save file</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer le fichier</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/>
+ <source>Unsaved document</source>
+ <translation>Document non enregistré</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/>
+ <source>The document &quot;%1&quot; has been modified. Do you want to save your changes?&lt;br/&gt;</source>
+ <translation>Le document &quot;% 1&quot; a été modifié.Voulez-vous enregistrer vos modifications? &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/>
+ <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
+ <translation>&lt;B&gt; REMARQUE: &lt;/ B&gt; Si vous ne enregistrez pas ces fichiers, toutes les modifications sont perdues. &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/>
<source>Application</source>
- <translation type="unfinished"></translation>
+ <translation>Application</translation>
</message>
+</context>
+<context>
+ <name>UpdateTab</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/>
- <source>Cannot read file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/>
+ <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source>
+ <translation>Il est recommandé de vérifier toujours la version de GPGFRontend et de la mise à niveau vers la dernière version.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/>
- <source>File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/>
+ <source>New versions not only represent new features, but also often represent functional and security fixes.</source>
+ <translation>De nouvelles versions représentent non seulement de nouvelles fonctionnalités, mais également des corrections fonctionnelles et de sécurité.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/>
- <source>Cannot write file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/>
+ <source>Current Version: </source>
+ <translation>Version actuelle:</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/>
- <source>Unsaved document</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/>
+ <source>The current version is inconsistent with the latest version on github.</source>
+ <translation>La version actuelle est incompatible avec la dernière version sur GitHub.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/>
- <source>&lt;h3&gt;The document &quot;%1&quot; has been modified.&lt;br/&gt;Do you want to save your changes?&lt;/h3&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/>
+ <source>Please click &lt;a href=&quot;https://github.com/saturneric/GpgFrontend/releases&quot;&gt;here&lt;/a&gt; to download the latest version.</source>
+ <translation>S&apos;il vous plaît cliquez sur &lt;a href=&quot;htttps://github.com/saturneric/gpgfronte/relases&quot;&gt; ici &lt;/a&gt; pour télécharger la dernière version.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
- <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/>
+ <source>Latest Version From Github: </source>
+ <translation>Dernière version de GitHub:</translation>
</message>
</context>
<context>
@@ -2987,32 +3296,32 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="32"/>
<source>Signature Details</source>
- <translation type="unfinished"></translation>
+ <translation>Détails de la signature</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="53"/>
<source>Status: </source>
- <translation type="unfinished"></translation>
+ <translation>Statut:</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="56"/>
<source>No valid input found</source>
- <translation type="unfinished"></translation>
+ <translation>Aucune entrée valide trouvée</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="67"/>
<source>Error Validating signature</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur lors de la validation de la signature</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="70"/>
<source>File was signed on %1 &lt;br/&gt; It Contains:&lt;br/&gt;&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Le fichier a été signé sur% 1 &lt;br/&gt; contient: &lt;br/&gt; &lt;br/&gt;</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="72"/>
<source>Signed on %1 &lt;br/&gt; It Contains:&lt;br /&gt;&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Signé sur% 1 &lt;br/&gt; Il contient: &lt;br /&gt; &lt;br/&gt;</translation>
</message>
</context>
<context>
@@ -3020,22 +3329,22 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="36"/>
<source>Import from keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Importer à partir de Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="39"/>
<source>Key not present with id 0x</source>
- <translation type="unfinished"></translation>
+ <translation>Clé non présente avec ID 0x</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="43"/>
<source>Status:</source>
- <translation type="unfinished"></translation>
+ <translation>Statut:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="45"/>
<source>Key not present in keylist</source>
- <translation type="unfinished"></translation>
+ <translation>Clé non présente dans Keylist</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="58"/>
@@ -3045,7 +3354,7 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="115"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="129"/>
<source>Key Information is NOT Available</source>
- <translation type="unfinished"></translation>
+ <translation>Les informations clés ne sont pas disponibles</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="60"/>
@@ -3055,103 +3364,103 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="117"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="131"/>
<source>Fingerprint: </source>
- <translation type="unfinished"></translation>
+ <translation>Empreinte digitale:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="67"/>
<source>Status: Cert Revoked</source>
- <translation type="unfinished"></translation>
+ <translation>Statut: certificat révoqué</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="81"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="95"/>
<source>Status: Signature Expired</source>
- <translation type="unfinished"></translation>
+ <translation>Statut: Signature EXPIRÉ</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="96"/>
<source>Status: Key Expired</source>
- <translation type="unfinished"></translation>
+ <translation>Statut: clé expirée</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="110"/>
<source>Status: General Error</source>
- <translation type="unfinished"></translation>
+ <translation>Statut: erreur générale</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="124"/>
<source>Status: Unknown Error</source>
- <translation type="unfinished"></translation>
+ <translation>Statut: erreur inconnue</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="159"/>
<source>Signer Name:</source>
- <translation type="unfinished"></translation>
+ <translation>Nom du signataire:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="160"/>
<source>Signer Email:</source>
- <translation type="unfinished"></translation>
+ <translation>Signer Email:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="161"/>
<source>Key&apos;s Fingerprint:</source>
- <translation type="unfinished"></translation>
+ <translation>Empreinte digitale de la clé:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="162"/>
<source>Valid:</source>
- <translation type="unfinished"></translation>
+ <translation>Valide:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="163"/>
<source>Flags:</source>
- <translation type="unfinished"></translation>
+ <translation>Drapeaux:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="171"/>
<source>Fully Valid</source>
- <translation type="unfinished"></translation>
+ <translation>Entièrement valable</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="173"/>
<source>NOT Fully Valid</source>
- <translation type="unfinished"></translation>
+ <translation>Pas complètement valide</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="180"/>
<source>Good </source>
- <translation type="unfinished"></translation>
+ <translation>Bien</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="183"/>
<source>Bad </source>
- <translation type="unfinished"></translation>
+ <translation>Mal</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="186"/>
<source>Expired </source>
- <translation type="unfinished"></translation>
+ <translation>Expiré</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="189"/>
<source>Missing Key </source>
- <translation type="unfinished"></translation>
+ <translation>Clé manquante</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="192"/>
<source>Revoked Key </source>
- <translation type="unfinished"></translation>
+ <translation>Clé révoquée</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="195"/>
<source>Expired Key </source>
- <translation type="unfinished"></translation>
+ <translation>Clé expirée</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="198"/>
<source>Missing CRL </source>
- <translation type="unfinished"></translation>
+ <translation>CRL manquant</translation>
</message>
</context>
<context>
@@ -3159,33 +3468,33 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/Wizard.cpp" line="46"/>
<source>First Start Wizard</source>
- <translation type="unfinished"></translation>
+ <translation>Assistant de premier départ</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="76"/>
<source>Import Error</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur d&apos;importation</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="76"/>
<source>Couldn&apos;t locate any keyring file in %1</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de localiser un fichier de porte-clés en% 1</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="84"/>
<location filename="../../src/ui/Wizard.cpp" line="95"/>
<source>Import error</source>
- <translation type="unfinished"></translation>
+ <translation>Erreur d&apos;importation</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="85"/>
<source>Couldn&apos;t open private keyringfile: %1</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible d&apos;ouvrir le keyRingfile privé:% 1</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="96"/>
<source>Couldn&apos;t open public keyringfile: %1</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible d&apos;ouvrir le keyRingfile publique:% 1</translation>
</message>
</context>
</TS>
diff --git a/resource/ts/gpg_frontend_ru.ts b/resource/ts/gpgfrontend_ru.ts
index ccbd15a0..65fb3765 100644
--- a/resource/ts/gpg_frontend_ru.ts
+++ b/resource/ts/gpgfrontend_ru.ts
@@ -4,212 +4,197 @@
<context>
<name>AboutDialog</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="29"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/>
<source>About </source>
- <translation type="unfinished"></translation>
+ <translation>О</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="35"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/>
<source>General</source>
- <translation type="unfinished"></translation>
+ <translation>Общий</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="36"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/>
<source>Translators</source>
- <translation type="unfinished"></translation>
+ <translation>Переводчики</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/>
+ <source>Update</source>
+ <translation>Обновлять</translation>
</message>
</context>
<context>
<name>AdvancedTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="580"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="679"/>
<source>Show Steganography Options [Advanced]</source>
- <translation type="unfinished"></translation>
+ <translation>Показать объекты стеганографии [Advanced]</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="582"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="681"/>
<source>Show Steganographic Options.</source>
- <translation type="unfinished"></translation>
+ <translation>Показать стеганографические варианты.</translation>
</message>
</context>
<context>
<name>AppearanceTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="368"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="444"/>
<source>Iconsize</source>
- <translation type="unfinished"></translation>
+ <translation>Iconsize.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="370"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="446"/>
<source>small</source>
- <translation type="unfinished"></translation>
+ <translation>небольшой</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="371"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="447"/>
<source>medium</source>
- <translation type="unfinished"></translation>
+ <translation>Средняя</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="372"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="448"/>
<source>large</source>
- <translation type="unfinished"></translation>
+ <translation>большой</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="388"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="464"/>
<source>Iconstyle</source>
- <translation type="unfinished"></translation>
+ <translation>Iconstyle.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="390"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="466"/>
<source>just text</source>
- <translation type="unfinished"></translation>
+ <translation>просто текст</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="391"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="467"/>
<source>just icons</source>
- <translation type="unfinished"></translation>
+ <translation>Просто иконы</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="392"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="468"/>
<source>text and icons</source>
- <translation type="unfinished"></translation>
+ <translation>текст и значки</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="484"/>
<source>Windowstate</source>
- <translation type="unfinished"></translation>
+ <translation>Indowstate.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="411"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="487"/>
<source>Save window size and position on exit.</source>
- <translation type="unfinished"></translation>
+ <translation>Сохранить размер окна и положение на выходе.</translation>
</message>
-</context>
-<context>
- <name>AttachmentTableModel</name>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/>
- <source>Filename</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="495"/>
+ <source>Information Board</source>
+ <translation>Доска объявлений</translation>
</message>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/>
- <source>Contenttype</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="501"/>
+ <source> Front Size</source>
+ <translation>Передний размер</translation>
</message>
</context>
<context>
- <name>Attachments</name>
- <message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/>
- <source>Save File</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/>
- <source>Save this file</source>
- <translation type="unfinished"></translation>
- </message>
+ <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/>
- <source>Open File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="165"/>
+ <source>Choose your action...</source>
+ <translation>Выберите свое действие ...</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/>
- <source>Open this file</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="166"/>
+ <source>...by clicking on the appropriate link.</source>
+ <translation>... нажав на соответствующую ссылку.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/>
- <source>File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="168"/>
+ <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
+ <translation>Если вы никогда не использовали GPGFRontend раньше, а также не владеть ключом GPG, но вы, возможно, хотите прочитать, как</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/>
- <source>Cannot write file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="170"/>
+ <source>Generate Key</source>
+ <translation>Генерировать ключ</translation>
</message>
-</context>
-<context>
- <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="161"/>
- <source>Choose your action...</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="176"/>
+ <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source>
+ <translation>Если вы хотите узнать, как зашифровать, расшифровать, подписать и проверить текст, вы можете прочитать</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="162"/>
- <source>...by clicking on the appropriate link.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <source>Encrypt &amp; Decrypt Text</source>
+ <translation>Шифра и расшифровывать текст</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="164"/>
- <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>or</source>
+ <translation>или же</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="172"/>
- <source>If you want to learn how to encrypt and decrypt text, you can read </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="180"/>
+ <source>Sign &amp; Verify Text</source>
+ <translation>Знак и проверить текст</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="174"/>
- <location filename="../../src/ui/Wizard.cpp" line="183"/>
- <source>this document</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="188"/>
+ <source>If you want to operate file, you can read </source>
+ <translation>Если вы хотите управлять файлом, вы можете прочитать</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="181"/>
- <source>If you want to sign and verify text, you can read </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>Encrypt &amp; Sign File</source>
+ <translation>Шифра и файл знака</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="166"/>
- <source>create a new keypair</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="192"/>
+ <source>Sign &amp; Verify File</source>
+ <translation>Знак и проверять файл</translation>
</message>
</context>
<context>
<name>ConclusionPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="397"/>
+ <location filename="../../src/ui/Wizard.cpp" line="407"/>
<source>Ready.</source>
- <translation type="unfinished"></translation>
+ <translation>Готовый.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="398"/>
+ <location filename="../../src/ui/Wizard.cpp" line="408"/>
<source>Have fun with GPGFrontend!</source>
- <translation type="unfinished"></translation>
+ <translation>Веселитесь с GPGFRontend!</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="400"/>
+ <location filename="../../src/ui/Wizard.cpp" line="410"/>
<source>You are ready to use GPGFrontend now.&lt;br&gt;&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Вы готовы использовать GPGFRontend сейчас. &lt;br&gt; &lt;br&gt; &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="402"/>
+ <location filename="../../src/ui/Wizard.cpp" line="412"/>
<source>The Online Document</source>
- <translation type="unfinished"></translation>
+ <translation>Онлайн документ</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="403"/>
+ <location filename="../../src/ui/Wizard.cpp" line="413"/>
<source> will get you started with GPGFrontend. It will open in the main window.&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Получу, вы начали с GPGFRontend.Он откроется в главном окне. &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="410"/>
+ <location filename="../../src/ui/Wizard.cpp" line="420"/>
<source>Open offline help.</source>
- <translation type="unfinished"></translation>
+ <translation>Откройте автономную помощь.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="413"/>
+ <location filename="../../src/ui/Wizard.cpp" line="423"/>
<source>Dont show the wizard again.</source>
- <translation type="unfinished"></translation>
+ <translation>Не показывать волшебник снова.</translation>
</message>
</context>
<context>
@@ -217,129 +202,152 @@
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="32"/>
<source>Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Дешифративный файл</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="34"/>
<source>Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Зашифруйте файл</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="36"/>
<source>Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>Знак файла</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="38"/>
<source>Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>Проверьте файл</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="47"/>
<source>Input Parameters</source>
- <translation type="unfinished"></translation>
+ <translation>Входные параметры</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="53"/>
<source>Target File</source>
- <translation type="unfinished"></translation>
+ <translation>Целевой файл</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="59"/>
<source>Output File</source>
- <translation type="unfinished"></translation>
+ <translation>Выходной файл</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="75"/>
<source>Signature File(.sig) Path</source>
- <translation type="unfinished"></translation>
+ <translation>Подпись файла (.сиг) путь</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="134"/>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="177"/>
<source>Open File</source>
- <translation type="unfinished"></translation>
+ <translation>Открыть файл</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="165"/>
<source>Save File</source>
- <translation type="unfinished"></translation>
+ <translation>Сохранить файл</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
<source>Couldn&apos;t open file</source>
- <translation type="unfinished"></translation>
+ <translation>Не мог открыть файл</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/>
+ <source>Error</source>
+ <translation>Ошибка</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/>
+ <source>Error Occurred During Encryption</source>
+ <translation>Произошла ошибка во время шифрования</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/>
+ <source>Error Occurred During Decryption</source>
+ <translation>Произошла ошибка во время дешифрования</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
+ <source>Error Occurred During Signature</source>
+ <translation>Произошла ошибка во время подписи</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/>
<source>File</source>
- <translation type="unfinished"></translation>
+ <translation>Файл</translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/>
<source>File exists! Do you want to overwrite it?</source>
- <translation type="unfinished"></translation>
+ <translation>Файл существует!Вы хотите перезаписать это?</translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/>
<source>Cannot write file %1:
%2.</source>
- <translation type="unfinished"></translation>
+ <translation>Невозможно написать файл% 1:
+% 2.</translation>
</message>
</context>
<context>
<name>FilePage</name>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/>
<source>Open</source>
- <translation type="unfinished"></translation>
+ <translation>Открыть</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/>
<source>Delete</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/>
<source>Encrypt and Sign</source>
- <translation type="unfinished"></translation>
+ <translation>Шифровать и подписать</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/>
<source>Decrypt and Verify</source>
- <translation type="unfinished"></translation>
+ <translation>Расшифровать и проверить</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/>
<source>Only Sign</source>
- <translation type="unfinished"></translation>
+ <translation>Только знак</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/>
<source>Only Verify</source>
- <translation type="unfinished"></translation>
+ <translation>Только проверить</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>Предупреждение</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/>
<source>Are you sure you want to delete it?</source>
- <translation type="unfinished"></translation>
+ <translation>Вы уверены, что хотите это удалить?</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/>
<source>Error</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/>
<source>Unable to delete the file or folder.</source>
- <translation type="unfinished"></translation>
+ <translation>Невозможно удалить файл или папку.</translation>
</message>
</context>
<context>
@@ -347,266 +355,281 @@
<message>
<location filename="../../src/ui/FindWidget.cpp" line="38"/>
<source>Find:</source>
- <translation type="unfinished"></translation>
+ <translation>Находить:</translation>
</message>
</context>
<context>
<name>GeneralTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="135"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="137"/>
<source>Remember Password</source>
- <translation type="unfinished"></translation>
+ <translation>Напомнить пароль</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="138"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="140"/>
<source>Remember password until closing gpg4usb</source>
- <translation type="unfinished"></translation>
+ <translation>Запомните пароль до закрытия GPG4UUSB</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="145"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="147"/>
<source>Save Checked Keys</source>
- <translation type="unfinished"></translation>
+ <translation>Сохранить проверенные ключи</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="148"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="150"/>
<source>Save checked private keys on exit and restore them on next start.</source>
- <translation type="unfinished"></translation>
+ <translation>Сохранить проверенные закрытые ключи на выходе и восстановить их на следующем запуске.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="157"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="159"/>
<source>Confirm drag&apos;n&apos;drop key import</source>
- <translation type="unfinished"></translation>
+ <translation>Подтвердите импорт ключа Drag&apos;n&apos;drop</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="162"/>
<source>Import files dropped on the keylist without confirmation.</source>
- <translation type="unfinished"></translation>
+ <translation>Файлы импорта упали на кейлист без подтверждения.</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="167"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="169"/>
<source>Language</source>
- <translation type="unfinished"></translation>
+ <translation>Язык</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="176"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="178"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; GpgFrontend will restart automatically if you change the language!</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;b&gt; Примечание: &lt;/ b&gt; gpgfrontend автоматически перезагрузится, если вы измените язык!</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="185"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="187"/>
<source>Own key</source>
- <translation type="unfinished"></translation>
+ <translation>Собственный ключ</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="193"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="195"/>
<source>&lt;none&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;none&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="207"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="209"/>
<source>Key pair for synchronization and identity authentication</source>
- <translation type="unfinished"></translation>
+ <translation>Пара ключей для синхронизации и аутентификации идентичности</translation>
</message>
</context>
<context>
<name>GpgME::GpgContext</name>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="90"/>
- <source>ENV Loading Failed</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="91"/>
- <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="577"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="528"/>
<source>Wrong password</source>
- <translation type="unfinished"></translation>
+ <translation>Неправильный пароль</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="585"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="536"/>
<source>Enter Password for</source>
- <translation type="unfinished"></translation>
+ <translation>Введите пароль для</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="589"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="540"/>
<source>Enter Password</source>
- <translation type="unfinished"></translation>
+ <translation>Введите пароль</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>Key Selection</source>
- <translation type="unfinished"></translation>
+ <translation>Выбор ключа</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>No Private Key Selected</source>
- <translation type="unfinished"></translation>
+ <translation>Нет закрытого ключа</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="804"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="746"/>
<source>Error in signing:</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка в подписании:</translation>
</message>
</context>
<context>
<name>GpgPathsTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="612"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="711"/>
<source>Relative path to keydb</source>
- <translation type="unfinished"></translation>
+ <translation>Относительный путь к Keydb</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="625"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="724"/>
<source>Current keydb path: </source>
- <translation type="unfinished"></translation>
+ <translation>Текущий путь ключей:</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="630"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="729"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; Gpg4usb will restart automatically if you change the keydb path!</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;b&gt; Примечание: &lt;/ b&gt; GPG4USB автоматически перезагрузится, если вы измените путь ключей!</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="659"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="758"/>
<source>Choose keydb directory</source>
- <translation type="unfinished"></translation>
+ <translation>Выберите каталог keydb.</translation>
</message>
</context>
<context>
<name>ImportFromGnupgPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="292"/>
+ <location filename="../../src/ui/Wizard.cpp" line="302"/>
<source>Import keys...</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт клавиш ...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="293"/>
+ <location filename="../../src/ui/Wizard.cpp" line="303"/>
<source>...from existing GnuPG installation</source>
- <translation type="unfinished"></translation>
+ <translation>... Из существующей установки GNUPG</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="295"/>
+ <location filename="../../src/ui/Wizard.cpp" line="305"/>
<source>You can import keys from a locally installed GnuPG.&lt;br&gt;&lt;br&gt; The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Вы можете импортировать ключи от локально установленного GNUPG. &lt;br&gt; &lt;br&gt; Местоположение читается из реестра в Windows или предполагается, что папка .gnupg в вашем домашнем каталоге в Linux. &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="299"/>
+ <location filename="../../src/ui/Wizard.cpp" line="309"/>
<source>Import keys from GnuPG</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт клавиш от GNUPG</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Import Error</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка импорта</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Couldn&apos;t locate GnuPG home directory</source>
- <translation type="unfinished"></translation>
+ <translation>Не мог найти домашний каталог GNUPG</translation>
</message>
</context>
<context>
<name>ImportFromGpg4usbPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="215"/>
+ <location filename="../../src/ui/Wizard.cpp" line="225"/>
<source>Import from...</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт из ...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="216"/>
+ <location filename="../../src/ui/Wizard.cpp" line="226"/>
<source>...existing GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>... Существующие GPGFRontend</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="218"/>
+ <location filename="../../src/ui/Wizard.cpp" line="228"/>
<source>You can import keys and/or settings from existing GPGFrontend. &lt;br&gt;&lt;br&gt;Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source>
- <translation type="unfinished"></translation>
+ <translation>Вы можете импортировать ключи и / или настройки из существующих GPGFRontend.&lt;br&gt; &lt;br&gt; &lt;br&gt; Просто проверьте, что вы хотите импортировать, нажмите кнопку «Импорт» и выберите каталог других GPGFRontend в диалоговом окне появления файла.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="225"/>
+ <location filename="../../src/ui/Wizard.cpp" line="235"/>
<source>Keys</source>
- <translation type="unfinished"></translation>
+ <translation>Ключи</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="229"/>
+ <location filename="../../src/ui/Wizard.cpp" line="239"/>
<source>Configuration</source>
- <translation type="unfinished"></translation>
+ <translation>Конфигурация</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="231"/>
+ <location filename="../../src/ui/Wizard.cpp" line="241"/>
<source>Import from GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт от GPGFRontend</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="246"/>
+ <location filename="../../src/ui/Wizard.cpp" line="256"/>
<source>Other GPGFrontend directory</source>
- <translation type="unfinished"></translation>
+ <translation>Другие каталога GPGFRontend</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="265"/>
+ <location filename="../../src/ui/Wizard.cpp" line="275"/>
<source>Configuration Imported</source>
- <translation type="unfinished"></translation>
+ <translation>Конфигурация импортирована</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="266"/>
+ <location filename="../../src/ui/Wizard.cpp" line="276"/>
<source>Imported Configuration from old GPGFrontend.&lt;br&gt;Will now restart to activate the configuration.</source>
- <translation type="unfinished"></translation>
+ <translation>Импортированная конфигурация из старых GPGFRontend. &lt;br&gt; теперь перезагрузится, чтобы активировать конфигурацию.</translation>
</message>
</context>
<context>
<name>InfoBoardWidget</name>
<message>
- <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/>
<source>Import missing key from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Импортировать недостающий ключ от Keyserver</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/>
+ <source>Optional Actions Menu</source>
+ <translation>Дополнительные действия меню действий</translation>
</message>
</context>
<context>
<name>InfoTab</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="55"/>
- <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, &lt;br&gt;cross-platform, and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/>
+ <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, cross-platform, &lt;br&gt;and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
+ <translation>&lt;br&gt; &lt;Center&gt; GPGFRontend - это простое в использовании, компактной, кроссплатформе, &lt;br&gt; и без установочного интерфейса GPG. &lt;br&gt; это визуализирует большую часть общих операций команд GPG. &lt;BR&gt; Он лицензирован под GPL V3 &lt;br&gt; &lt;br&gt; &lt;b&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; Если у вас есть какие-либо вопросы или предложения, повысить проблему &lt;br/&gt;href = &quot;https://github.com/saturneric/gpgfrontend&quot;&gt; github &lt;/a&gt; или отправьте письмо в мой список рассылки на &lt;a href=&quot;mailte: @bktus.com&quot;&gt; [email protected] &lt;/ a&gt;.</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="63"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/>
<source>&lt;br&gt;&lt;br&gt; Built with Qt </source>
- <translation type="unfinished"></translation>
+ <translation>&lt;br&gt; &lt;br&gt; построен с Qt</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="64"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/>
<source> and GPGME </source>
- <translation type="unfinished"></translation>
+ <translation>и GPGME</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="65"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/>
<source>&lt;br&gt;Built at </source>
- <translation type="unfinished"></translation>
+ <translation>&lt;br&gt; построен</translation>
</message>
</context>
<context>
<name>IntroPage</name>
<message>
<location filename="../../src/ui/Wizard.cpp" line="111"/>
- <source>Getting started...</source>
- <translation type="unfinished"></translation>
+ <source>Getting Started...</source>
+ <translation>Начиная...</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="112"/>
<source>... with GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>... с gpgfrontend</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="114"/>
- <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.&lt;br&gt;&lt;br&gt;For more information have a look at the &lt;a href=&apos;docu_concepts.html&apos;&gt;concepts&lt;/a&gt; (by clicking the link, the page will open in the main window). &lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source>
+ <translation>Добро пожаловать использовать GPGFRontend для расшифровки и подписания текста или файла!</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="116"/>
+ <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source>
+ <translation>Является мощным, простым в использовании, компактной, кроссплатформенной и монтажной программой Crypto Crypto OpenPGP.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="117"/>
+ <source>For brief information have a look at the</source>
+ <translation>Для краткой информации посмотрите на</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="118"/>
+ <source>Overview</source>
+ <translation>Обзор</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="123"/>
+ <location filename="../../src/ui/Wizard.cpp" line="119"/>
+ <source>by clicking the link, the page will open in the web browser</source>
+ <translation>Нажав на ссылку, страница откроется в веб-браузере</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="127"/>
<source>Choose a Language</source>
- <translation type="unfinished"></translation>
+ <translation>Выберите язык</translation>
</message>
</context>
<context>
@@ -614,22 +637,22 @@
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="31"/>
<source>KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>Keypair.</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="32"/>
<source>UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>UIDs</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="33"/>
<source>Subkeys</source>
- <translation type="unfinished"></translation>
+ <translation>Подсказки</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="40"/>
<source>Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>Основные детали</translation>
</message>
</context>
<context>
@@ -637,150 +660,159 @@
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="32"/>
<source>Generate Key</source>
- <translation type="unfinished"></translation>
+ <translation>Генерировать ключ</translation>
</message>
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="68"/>
<source> Name must contain at least five characters.
</source>
- <translation type="unfinished"></translation>
+ <translation>Имя должно содержать не менее пяти символов.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="70"/>
<source> Please give a email address.
</source>
- <translation type="unfinished"></translation>
+ <translation>Пожалуйста, дайте адрес электронной почты.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/>
- <source> Expiration time no more than 2 years. </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/>
+ <source> Expiration time no more than 2 years.
+</source>
+ <translation>Время истечения не более 2 лет.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/>
<source>Generating Key...</source>
- <translation type="unfinished"></translation>
+ <translation>Генератор ключа ...</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/>
<source>Collecting random data for key generation.
This may take a while.
To speed up the process use your computer
(e.g. browse the net, listen to music,...)</source>
- <translation type="unfinished"></translation>
+ <translation>Сбор случайных данных для генерации ключей.
+ Это может занять некоторое время.
+ Чтобы ускорить процесс, используйте свой компьютер
+ (например, просмотрите чистую, слушаю музыку, ...)</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/>
+ <source>Key Usage</source>
+ <translation>Ключевое использование</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/>
<source>Encryption</source>
- <translation type="unfinished"></translation>
+ <translation>Шифрование</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/>
<source>Signing</source>
- <translation type="unfinished"></translation>
+ <translation>Подписание</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/>
<source>Certification</source>
- <translation type="unfinished"></translation>
+ <translation>Сертификация</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/>
<source>Authentication</source>
- <translation type="unfinished"></translation>
+ <translation>Аутентификация</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>Success</source>
- <translation type="unfinished"></translation>
+ <translation>Успех</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>The new key pair has been generated.</source>
- <translation type="unfinished"></translation>
+ <translation>Новая ключевая пара была сгенерирована.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>Failure</source>
- <translation type="unfinished"></translation>
+ <translation>Отказ</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>An error occurred during key generation.</source>
- <translation type="unfinished"></translation>
+ <translation>Произошла ошибка во время генерации ключей.</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/>
<source>Name:</source>
- <translation type="unfinished"></translation>
+ <translation>Имя:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
<source>Email Address:</source>
- <translation type="unfinished"></translation>
+ <translation>Адрес электронной почты:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
<source>Comment:</source>
- <translation type="unfinished"></translation>
+ <translation>Комментарий:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
<source>Expiration Date:</source>
- <translation type="unfinished"></translation>
+ <translation>Дата окончания срока:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>Никогда не истекаешь</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
<source>KeySize (in Bit):</source>
- <translation type="unfinished"></translation>
+ <translation>Клинизировать (по-бит):</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
<source>Key Type:</source>
- <translation type="unfinished"></translation>
+ <translation>Тип ключа:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
<source>Non Pass Phrase</source>
- <translation type="unfinished"></translation>
+ <translation>Не проходящая фраза</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/>
<source>Basic Information</source>
- <translation type="unfinished"></translation>
+ <translation>Основная информация</translation>
</message>
</context>
<context>
<name>KeyGenPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="356"/>
+ <location filename="../../src/ui/Wizard.cpp" line="366"/>
<source>Create a keypair...</source>
- <translation type="unfinished"></translation>
+ <translation>Создать клавиатуру ...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="357"/>
+ <location filename="../../src/ui/Wizard.cpp" line="367"/>
<source>...for decrypting and signing messages</source>
- <translation type="unfinished"></translation>
+ <translation>... Для расшифровки и подписания сообщений</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="358"/>
+ <location filename="../../src/ui/Wizard.cpp" line="368"/>
<source>You should create a new keypair.The pair consists of a public and a private key.&lt;br&gt;Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.&lt;br&gt;For more information have a look at the offline tutorial (which then is shown in the main window):</source>
- <translation type="unfinished"></translation>
+ <translation>Вы должны создать новую keypair. Пара состоит из публики и закрытого ключа. &lt;br&gt; Другие пользователи могут использовать открытый ключ для шифрования сообщений для вас и проверить сообщения, подписанные вами. Вы можете использовать закрытый ключ для расшифровки и подписатьСообщения. &lt;br&gt; Для получения дополнительной информации посмотрите на автономный учебник (который затем отображается в главном окне):</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="365"/>
+ <location filename="../../src/ui/Wizard.cpp" line="375"/>
<source>Offline tutorial</source>
- <translation type="unfinished"></translation>
+ <translation>Оффлайн учебник</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="372"/>
+ <location filename="../../src/ui/Wizard.cpp" line="382"/>
<source>Create New Key</source>
- <translation type="unfinished"></translation>
+ <translation>Создать новый ключ</translation>
</message>
</context>
<context>
@@ -789,118 +821,118 @@
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="53"/>
<source>Key Update Details</source>
- <translation type="unfinished"></translation>
+ <translation>Детали обновления ключа</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/>
<source>No keys found</source>
- <translation type="unfinished"></translation>
+ <translation>Ключи не найдены</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="55"/>
<source>Key Import Details</source>
- <translation type="unfinished"></translation>
+ <translation>Детали ввоза ключей</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/>
<source>No keys found to import</source>
- <translation type="unfinished"></translation>
+ <translation>Клавиши не найдены для импорта</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="64"/>
<source>General key info</source>
- <translation type="unfinished"></translation>
+ <translation>Общая ключевая информация</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="67"/>
<source>Considered:</source>
- <translation type="unfinished"></translation>
+ <translation>Считается:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="71"/>
<source>Public unchanged:</source>
- <translation type="unfinished"></translation>
+ <translation>Общественность без изменений:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="76"/>
<source>Imported:</source>
- <translation type="unfinished"></translation>
+ <translation>Импортирован:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="81"/>
<source>Not imported:</source>
- <translation type="unfinished"></translation>
+ <translation>Не импортировано:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="86"/>
<source>Private read:</source>
- <translation type="unfinished"></translation>
+ <translation>Частный читал:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="91"/>
<source>Private imported:</source>
- <translation type="unfinished"></translation>
+ <translation>Частный импорт:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="96"/>
<source>Private unchanged:</source>
- <translation type="unfinished"></translation>
+ <translation>Частный без изменений:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>Имя</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>Электронное письмо</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Status</source>
- <translation type="unfinished"></translation>
+ <translation>Статус</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Fingerprint</source>
- <translation type="unfinished"></translation>
+ <translation>Отпечаток пальца</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="135"/>
<source>private</source>
- <translation type="unfinished"></translation>
+ <translation>частный</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="138"/>
<source>public</source>
- <translation type="unfinished"></translation>
+ <translation>публичный</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="141"/>
<source>unchanged</source>
- <translation type="unfinished"></translation>
+ <translation>без изменений</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="144"/>
<source>new key</source>
- <translation type="unfinished"></translation>
+ <translation>новый ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="147"/>
<source>new subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Новый подраздел</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="151"/>
<source>new signature</source>
- <translation type="unfinished"></translation>
+ <translation>Новая подпись</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="155"/>
<source>new uid</source>
- <translation type="unfinished"></translation>
+ <translation>Новый UID</translation>
</message>
</context>
<context>
@@ -908,157 +940,158 @@
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Select</source>
- <translation type="unfinished"></translation>
+ <translation>Выбирать</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Type</source>
- <translation type="unfinished"></translation>
+ <translation>Тип</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>Имя</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Email Address</source>
- <translation type="unfinished"></translation>
+ <translation>Адрес электронной почты</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Usage</source>
- <translation type="unfinished"></translation>
+ <translation>Применение</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Validity</source>
- <translation type="unfinished"></translation>
+ <translation>Срок действия</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Finger Print</source>
- <translation type="unfinished"></translation>
+ <translation>Печать пальцев</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
<source>Import Keys</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт клавиш</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/>
<source>You&apos;ve dropped something on the table.
GpgFrontend will now try to import key(s).</source>
- <translation type="unfinished"></translation>
+ <translation>Вы что-то бросили на стол.
+ GPGFRontend теперь попробует импортировать ключ (ы).</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/>
<source>Always import without bothering.</source>
- <translation type="unfinished"></translation>
+ <translation>Всегда импортировать, не беспокоясь.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/>
<source>Couldn&apos;t Open File: </source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось открыть файл:</translation>
</message>
</context>
<context>
<name>KeyMgmt</name>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="81"/>
- <source>KeyPairs Management</source>
- <translation type="unfinished"></translation>
+ <source>Key Pair Management</source>
+ <translation>Ключевое управление паре</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="88"/>
<source>&amp;Open</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Открыть</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="89"/>
<source>Ctrl+O</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + O.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="90"/>
<source>Open Key File</source>
- <translation type="unfinished"></translation>
+ <translation>Откройте файл ключа</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="93"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Закрывать</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="94"/>
<source>Ctrl+Q</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + Q.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="96"/>
<source>Close</source>
- <translation type="unfinished"></translation>
+ <translation>Закрывать</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="99"/>
<source>New Keypair</source>
- <translation type="unfinished"></translation>
+ <translation>Новая клавиатура</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="100"/>
<source>Ctrl+N</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + N.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="102"/>
<source>Generate KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>Создать ключевую пару</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="105"/>
<source>New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Новый подраздел</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="106"/>
<source>Ctrl+Shift+N</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + Shift + N</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="108"/>
<source>Generate Subkey For Selected KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>Создать подраздел для выбранной клавиатуры</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="111"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="152"/>
<source>&amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Файл</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="113"/>
<source>Import New Key From File</source>
- <translation type="unfinished"></translation>
+ <translation>Импортировать новый ключ из файла</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="116"/>
<source>&amp;Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>И буфер обмена</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="118"/>
<source>Import New Key From Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Импортировать новый ключ из буфера обмена</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="121"/>
<source>&amp;Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="123"/>
<source>Import New Key From Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Импортировать новый ключ от Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="126"/>
@@ -1068,149 +1101,149 @@
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="128"/>
<source>Export Selected Key(s) To Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Экспорт выбранных клавиш в буфер обмена</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="131"/>
<source>Export To &amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>Экспорт в &amp; file</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="133"/>
<source>Export Selected Key(s) To File</source>
- <translation type="unfinished"></translation>
+ <translation>Экспорт выбранных клавиш (ы) в файл</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="136"/>
<source>Delete Selected Key(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить выбранные ключи (ы)</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="137"/>
<source>Delete the Selected keys</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить выбранные ключи</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="140"/>
<source>Delete Checked Key(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить проверенные ключи (ы)</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="141"/>
<source>Delete the Checked keys</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить проверенные ключи</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="145"/>
<source>Show Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>Показать ключевые детали</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="146"/>
<source>Show Details for this Key</source>
- <translation type="unfinished"></translation>
+ <translation>Показать детали для этого ключа</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="156"/>
<source>&amp;Key</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="157"/>
<source>&amp;Generate Key</source>
- <translation type="unfinished"></translation>
+ <translation>Генерировать ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="161"/>
<source>&amp;Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>И Импорт ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="173"/>
<source>Key</source>
- <translation type="unfinished"></translation>
+ <translation>Ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="181"/>
<source>Generate</source>
- <translation type="unfinished"></translation>
+ <translation>Генерация</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="182"/>
<source>Generate A New Keypair or Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Генерировать новую клавиатуру или подразделение</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="191"/>
<source>Import key</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="192"/>
<source>Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<source>Open Key</source>
- <translation type="unfinished"></translation>
+ <translation>Открыть ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="299"/>
<source>Key Files</source>
- <translation type="unfinished"></translation>
+ <translation>Ключевые файлы</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<source>Keyring files</source>
- <translation type="unfinished"></translation>
+ <translation>Ключевые файлы</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="218"/>
<source>Couldn&apos;t Open File: </source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось открыть файл:</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="268"/>
<source>Deleting Keys</source>
- <translation type="unfinished"></translation>
+ <translation>Удаление клавиш</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="269"/>
<source>Are you sure that you want to delete the following keys?</source>
- <translation type="unfinished"></translation>
+ <translation>Вы уверены, что хотите удалить следующие клавиши?</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="270"/>
<source>The action can not be undone.</source>
- <translation type="unfinished"></translation>
+ <translation>Действие не может быть отменено.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="299"/>
<source>Export Key To File</source>
- <translation type="unfinished"></translation>
+ <translation>Экспорт ключа в файл</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="309"/>
<source>key(s) exported</source>
- <translation type="unfinished"></translation>
+ <translation>Ключ (ы) экспортирован</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="338"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="345"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Неверная операция</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="339"/>
<source>Please select one KeyPair before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Пожалуйста, выберите одну клавиатуру перед этой операцией.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="346"/>
<source>If a key pair does not have a private key then it will not be able to generate sub-keys.</source>
- <translation type="unfinished"></translation>
+ <translation>Если ключевая пара не имеет частного ключа, то он не сможет генерировать подшиные клавиши.</translation>
</message>
</context>
<context>
@@ -1218,198 +1251,237 @@
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="40"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>Имя</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="41"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>Электронное письмо</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="42"/>
<source>Comment</source>
- <translation type="unfinished"></translation>
+ <translation>Комментарий</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="55"/>
<source>Create New UID</source>
- <translation type="unfinished"></translation>
+ <translation>Создать новый UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="68"/>
<source> Name must contain at least five characters.
</source>
- <translation type="unfinished"></translation>
+ <translation>Имя должно содержать не менее пяти символов.</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="70"/>
<source> Please give a email address.
</source>
- <translation type="unfinished"></translation>
+ <translation>Пожалуйста, дайте адрес электронной почты.</translation>
</message>
</context>
<context>
<name>KeyPairDetailTab</name>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
<source>Owner</source>
- <translation type="unfinished"></translation>
+ <translation>Владелец</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
<source>Master Key</source>
- <translation type="unfinished"></translation>
+ <translation>Отмычка</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/>
<source>Fingerprint</source>
- <translation type="unfinished"></translation>
+ <translation>Отпечаток пальца</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/>
<source>Additional UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>Дополнительные UID</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Exists</source>
+ <translation>Существуют</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Not Exists</source>
+ <translation>Не существует</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
<source>Name:</source>
- <translation type="unfinished"></translation>
+ <translation>Имя:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/>
<source>Email Address:</source>
- <translation type="unfinished"></translation>
+ <translation>Адрес электронной почты:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/>
<source>Comment:</source>
- <translation type="unfinished"></translation>
+ <translation>Комментарий:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
<source>Key ID: </source>
- <translation type="unfinished"></translation>
+ <translation>Ключевой идентификатор:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
<source>Algorithm: </source>
- <translation type="unfinished"></translation>
+ <translation>Алгоритм:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
<source>Key Size:</source>
- <translation type="unfinished"></translation>
+ <translation>Размер ключа:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
<source>Nominal Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>Номинальное использование:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
<source>Actual Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>Фактическое использование:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
<source>Expires on: </source>
- <translation type="unfinished"></translation>
+ <translation>Годен до:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/>
<source>Last Update: </source>
- <translation type="unfinished"></translation>
+ <translation>Последнее обновление:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/>
<source>Secret Key Existence: </source>
- <translation type="unfinished"></translation>
+ <translation>Секретное ключевое существование:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
<source>Copy</source>
- <translation type="unfinished"></translation>
+ <translation>Скопировать</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/>
<source>copy fingerprint to clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Скопируйте отпечаток пальца в буфер обмена</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/>
<source>Operations</source>
- <translation type="unfinished"></translation>
+ <translation>Операции</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/>
- <source>Export Private Key (Include Subkeys)</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/>
+ <source>Export Private Key (Include Subkey)</source>
+ <translation>Экспорт закрытый ключ (включить подразделение)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/>
<source>Modify Expiration Datetime (Master Key)</source>
- <translation type="unfinished"></translation>
+ <translation>Изменить истечения срока действия данных (главный ключ)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/>
<source>Key Server Operation (Pubkey)</source>
- <translation type="unfinished"></translation>
+ <translation>Операция ключевым сервером (PUBKEY)</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/>
+ <source>Generate Revoke Certificate</source>
+ <translation>Создать сертификат Revoke.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/>
<source>Warning: The Master Key has expired.</source>
- <translation type="unfinished"></translation>
+ <translation>ПРЕДУПРЕЖДЕНИЕ. Срок действия главного ключа истек.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/>
<source>Warning: The Master Key has been revoked</source>
- <translation type="unfinished"></translation>
+ <translation>Предупреждение: главный ключ был отменен</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/>
<source>Exporting private Key</source>
- <translation type="unfinished"></translation>
+ <translation>Экспорт закрытого ключа</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/>
- <source>&lt;h3&gt;You are about to export your &lt;font color=&quot;red&quot;&gt;PRIVATE KEY&lt;/font&gt;!&lt;/h3&gt;
-This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALLY want to export your PRIVATE KEY?</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/>
+ <source>You are about to export your</source>
+ <translation>Вы собираетесь экспортировать свой</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/>
+ <source>PRIVATE KEY</source>
+ <translation>Закрытый ключ</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/>
+ <source>This is NOT your Public Key, so DON&apos;T give it away.</source>
+ <translation>Это не ваш открытый ключ, поэтому не отдавай.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/>
+ <source>Do you REALLY want to export your PRIVATE KEY?</source>
+ <translation>Вы действительно хотите экспортировать свой закрытый ключ?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/>
<source>Export Key To File</source>
- <translation type="unfinished"></translation>
+ <translation>Экспорт ключа в файл</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/>
<source>Key Files</source>
- <translation type="unfinished"></translation>
+ <translation>Ключевые файлы</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Export Error</source>
- <translation type="unfinished"></translation>
+ <translation>Экспорт ошибок</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Couldn&apos;t open %1 for writing</source>
- <translation type="unfinished"></translation>
+ <translation>Не мог открыть% 1 для письма</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>Никогда не истекаешь</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/>
- <source>Upload Key Pair</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/>
+ <source>Upload Key Pair to Key Server</source>
+ <translation>Загрузить ключевую пару на ключевой сервер</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/>
<source>Update Key Pair</source>
- <translation type="unfinished"></translation>
+ <translation>Обновить ключевую пару</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/>
+ <source>Generate revocation certificate</source>
+ <translation>Генерировать сертификат отзыва</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/>
+ <source>Revocation Certificates</source>
+ <translation>Сертификаты отзыва</translation>
</message>
</context>
<context>
@@ -1417,87 +1489,87 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="37"/>
<source>Generate A New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Генерировать новый подразделение</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
<source>Key ID: </source>
- <translation type="unfinished"></translation>
+ <translation>Ключевой идентификатор:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
<source>Algorithm: </source>
- <translation type="unfinished"></translation>
+ <translation>Алгоритм:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
<source>Key Size:</source>
- <translation type="unfinished"></translation>
+ <translation>Размер ключа:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
<source>Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>Применение:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
<source>Expires On </source>
- <translation type="unfinished"></translation>
+ <translation>Годен до</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
<source>Last Update: </source>
- <translation type="unfinished"></translation>
+ <translation>Последнее обновление:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
<source>Existence: </source>
- <translation type="unfinished"></translation>
+ <translation>Существование:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/>
<source>Fingerprint: </source>
- <translation type="unfinished"></translation>
+ <translation>Отпечаток пальца:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Subkey ID</source>
- <translation type="unfinished"></translation>
+ <translation>ID SUBKEY ID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Key Size</source>
- <translation type="unfinished"></translation>
+ <translation>Размер ключа</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Algo</source>
- <translation type="unfinished"></translation>
+ <translation>Что-нибудь</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Create Date</source>
- <translation type="unfinished"></translation>
+ <translation>Создать дату</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>Дата истечения срока годности</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>Никогда не истекаешь</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/>
<source>Never Expires</source>
- <translation type="unfinished"></translation>
+ <translation>Никогда не заканчивается</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/>
<source>Edit Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>Редактировать дату истечения срока действия</translation>
</message>
</context>
<context>
@@ -1505,192 +1577,202 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="39"/>
<source>New UID</source>
- <translation type="unfinished"></translation>
+ <translation>Новый UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="40"/>
<source>UID Management</source>
- <translation type="unfinished"></translation>
+ <translation>Управление UID</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/>
+ <source>UIDs</source>
+ <translation>UIDs</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/>
+ <source>Signature of Selected UID</source>
+ <translation>Подпись выбранного UID</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Select</source>
- <translation type="unfinished"></translation>
+ <translation>Выбирать</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>Имя</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>Электронное письмо</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Comment</source>
- <translation type="unfinished"></translation>
+ <translation>Комментарий</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Key ID</source>
- <translation type="unfinished"></translation>
+ <translation>Идентификатор ключа</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Create Date</source>
- <translation type="unfinished"></translation>
+ <translation>Создать дату</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Expired Date</source>
- <translation type="unfinished"></translation>
+ <translation>Истекший срок</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/>
<source>Never Expires</source>
- <translation type="unfinished"></translation>
+ <translation>Никогда не заканчивается</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Неверная операция</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/>
<source>Please select one or more UIDs before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Пожалуйста, выберите один или несколько UID, прежде чем делать эту операцию.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/>
<source>Sign Selected UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Знак выбран UID (ы)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/>
<source>Delete Selected UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить выбранные UID (ы)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/>
<source>Successful Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Успешная операция</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
<source>Successfully added a new UID.</source>
- <translation type="unfinished"></translation>
+ <translation>Успешно добавил новый UID.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/>
<source>Operation Failed</source>
- <translation type="unfinished"></translation>
+ <translation>Операция не удалась</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/>
<source>An error occurred during the operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Во время операции произошла ошибка.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/>
<source>Deleting UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>Удаление UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/>
<source>Are you sure that you want to delete the following uids?</source>
- <translation type="unfinished"></translation>
+ <translation>Вы уверены, что хотите удалить следующие UID?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/>
<source>The action can not be undone.</source>
- <translation type="unfinished"></translation>
+ <translation>Действие не может быть отменено.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/>
<source>Set Primary UID</source>
- <translation type="unfinished"></translation>
+ <translation>Установите первичный UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/>
<source>Are you sure that you want to set the Primary UID to?</source>
- <translation type="unfinished"></translation>
+ <translation>Вы уверены, что хотите установить основной UID?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/>
<source>Set As Primary</source>
- <translation type="unfinished"></translation>
+ <translation>Установить как первичный</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/>
<source>Sign UID</source>
- <translation type="unfinished"></translation>
+ <translation>Знак UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/>
<source>Delete UID</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/>
<source>Please select one UID before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Пожалуйста, выберите один UID перед этой операцией.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/>
<source>Deleting UID</source>
- <translation type="unfinished"></translation>
+ <translation>Удаление UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/>
<source>Are you sure that you want to delete the following uid?</source>
- <translation type="unfinished"></translation>
+ <translation>Вы уверены, что хотите удалить следующий UID?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/>
<source>Delete(Revoke) Key Signature</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить (отозвать) подпись ключа</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/>
<source>Please select one Key Signature before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Пожалуйста, выберите одну клавишу подпись перед выполнением этой операции.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/>
<source>To delete the signature, you need to have its corresponding public key in the local database.</source>
- <translation type="unfinished"></translation>
+ <translation>Чтобы удалить подпись, вам нужно иметь соответствующий открытый ключ в локальной базе данных.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/>
<source>Deleting Key Signature</source>
- <translation type="unfinished"></translation>
+ <translation>Удаление подписи ключей</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/>
<source>Are you sure that you want to delete the following signature?</source>
- <translation type="unfinished"></translation>
+ <translation>Вы уверены, что хотите удалить следующую подпись?</translation>
</message>
</context>
<context>
@@ -1698,140 +1780,140 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="40"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Закрывать</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="41"/>
<source>&amp;Import ALL</source>
- <translation type="unfinished"></translation>
+ <translation>И импорт все</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="42"/>
<source>&amp;Search</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Поиск</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="45"/>
<source>Search String:</source>
- <translation type="unfinished"></translation>
+ <translation>Строка поиска:</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="49"/>
<source>Key Server:</source>
- <translation type="unfinished"></translation>
+ <translation>Ключевой сервер:</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="97"/>
<source>Update Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Обновлять ключи от Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="99"/>
<source>Import Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт клавиш от Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>UID</source>
- <translation type="unfinished"></translation>
+ <translation>UID</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>Creation date</source>
- <translation type="unfinished"></translation>
+ <translation>Дата создания</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>KeyID</source>
- <translation type="unfinished"></translation>
+ <translation>Кейд</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>Tag</source>
- <translation type="unfinished"></translation>
+ <translation>Тег</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/>
- <source>&lt;h4&gt;Text is empty.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Text is empty.</source>
+ <translation>Текст пуст.</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/>
<source>Not Key Found</source>
- <translation type="unfinished"></translation>
+ <translation>Не найден ключ</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/>
<source>Timeout</source>
- <translation type="unfinished"></translation>
+ <translation>Время ожидания</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/>
<source>Key Server Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>Ключевой сервер не найден</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/>
<source>Connection Error</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка соединения</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/>
- <source>&lt;h4&gt;CToo many responses from keyserver!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Too many responses from keyserver!</source>
+ <translation>Слишком много ответов от Keyserver!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/>
- <source>&lt;h4&gt;No keys found, input may be kexId, retrying search with 0x.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>No keys found, input may be kexId, retrying search with 0x.</source>
+ <translation>Не найдено ключей, вход может быть кекидом, повторный поиск с 0x.</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/>
- <source>&lt;h4&gt;No keys found containing the search string!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>No keys found containing the search string!</source>
+ <translation>Клавиши не найдены, содержащие строку поиска!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/>
- <source>&lt;h4&gt;Insufficiently specific search string!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Insufficiently specific search string!</source>
+ <translation>Недостаточно определенная строка поиска!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="274"/>
<source>revoked</source>
- <translation type="unfinished"></translation>
+ <translation>отзыв</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="277"/>
<source>disabled</source>
- <translation type="unfinished"></translation>
+ <translation>отключен</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="317"/>
<source>&lt;h4&gt;%1 keys found. Double click a key to import it.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;h4&gt;% 1 ключей найден.Дважды щелкните ключ, чтобы импортировать его. &lt;/ H4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="383"/>
<source>Key Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>Ключ не найден</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="410"/>
<source>&lt;h4&gt;Key Updated&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;h4&gt; ключ обновлен &lt;/ h4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="412"/>
<source>&lt;h4&gt;Key Imported&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;H4&gt; КЛЮЧ импортирован &lt;/ H4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="473"/>
<source>Upload Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Клавиши загрузки от Keyserver</translation>
</message>
</context>
<context>
@@ -1839,22 +1921,22 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="36"/>
<source>Confirm</source>
- <translation type="unfinished"></translation>
+ <translation>Подтверждать</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="41"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>Никогда не истекаешь</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="61"/>
<source>Operation Failed</source>
- <translation type="unfinished"></translation>
+ <translation>Операция не удалась</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="62"/>
<source>An error occurred during the operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Во время операции произошла ошибка.</translation>
</message>
</context>
<context>
@@ -1862,801 +1944,856 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="72"/>
<source>Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>Дата истечения срока годности</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="81"/>
<source>Sign For Key&apos;s UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>Знак для ключа UID (ы)</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="100"/>
<source>Unsuccessful Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Неудачная операция</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="101"/>
<source>Signature operation failed for UID </source>
- <translation type="unfinished"></translation>
+ <translation>Операция подписи не удалась для UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="108"/>
<source>Operation Complete</source>
- <translation type="unfinished"></translation>
+ <translation>Операция завершена</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="109"/>
<source>The signature operation of the UID is complete</source>
- <translation type="unfinished"></translation>
+ <translation>Эксплуатация подписи UID завершена</translation>
</message>
</context>
<context>
<name>KeyUploadDialog</name>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/>
<source>Uploading Public Key</source>
- <translation type="unfinished"></translation>
+ <translation>Загрузка открытого ключа</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/>
<source>Key Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>Ключ не найден</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/>
<source>Timeout</source>
- <translation type="unfinished"></translation>
+ <translation>Время ожидания</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/>
<source>Key Server Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>Ключевой сервер не найден</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/>
<source>Connection Error</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка соединения</translation>
</message>
</context>
<context>
<name>KeyserverTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="508"/>
- <source>Default Keyserver for import:</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="607"/>
+ <source>Default Key Server for import:</source>
+ <translation>Сервер по умолчанию для импорта:</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="525"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="624"/>
<source>Add</source>
- <translation type="unfinished"></translation>
+ <translation>Добавлять</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/>
+ <location filename="../../src/MainWindow.cpp" line="35"/>
+ <source>Loading Gnupg</source>
+ <translation>Загрузка GNUPG.</translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="62"/>
+ <source>ENV Loading Failed</source>
+ <translation>Загрузка ENV не удалась</translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="63"/>
+ <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
+ <translation>GNUPG не установлен правильно, пожалуйста, следуйте инструкциям ReadMe для установки GNUPG, а затем открыть GPGFRontend.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/>
<source>No Key Selected</source>
- <translation type="unfinished"></translation>
+ <translation>Нет выбранного ключа</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Неверная операция</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/>
<source>The selected key contains a key that does not actually have a encrypt usage.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Выбранный ключ содержит ключ, который на самом деле не имеет использование шифрования. &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/>
+ <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
+ <translation>&lt;br/&gt; Например, следующий ключ: &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/>
+ <source>Encrypting</source>
+ <translation>Шифрование</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/>
+ <source>Function Disabled</source>
+ <translation>Функция отключена</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/>
+ <source>Please go to the settings interface to enable and configure this function.</source>
+ <translation>Пожалуйста, перейдите на интерфейс настроек, чтобы включить и настроить эту функцию.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/>
<source>The selected key contains a key that does not actually have a signature usage.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Выбранный ключ содержит клавишу, на самом деле не имеет использование подписи. &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/>
+ <source>Signing</source>
+ <translation>Подписание</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/>
+ <source>Decrypting</source>
+ <translation>Расшифровка</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/>
+ <source>Verifying</source>
+ <translation>Проверка</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/>
<source>Invalid KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>Неверная keypair.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/>
<source>The selected keypair cannot be used for signing and encryption at the same time.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Выбранная клавиатура не может быть использована для подписания и шифрования одновременно. &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/>
<source>Incomplete Operation</source>
- <translation type="unfinished"></translation>
+ <translation>Неполная операция</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/>
<source>None of the selected key pairs can provide the encryption function.</source>
- <translation type="unfinished"></translation>
+ <translation>Ни одна из выбранных парных пар не может предоставлять функцию шифрования.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/>
<source>None of the selected key pairs can provide the signature function.</source>
- <translation type="unfinished"></translation>
+ <translation>Ни одна из выбранных парных пар не может обеспечить функцию подписи.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/>
+ <source>Encrypting and Signing</source>
+ <translation>Шифрование и подписание</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/>
+ <source>Decrypting and Verifying</source>
+ <translation>Расшифровка и проверка</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>Error</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <source>Select a file before doing it.</source>
+ <translation>Выберите файл перед этим.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
<source>No permission to read this file.</source>
- <translation type="unfinished"></translation>
+ <translation>Нет разрешения на чтение этого файла.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
<source>No permission to create file.</source>
- <translation type="unfinished"></translation>
+ <translation>Нет разрешения на создание файла.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>Предупреждение</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/>
<source>The target file already exists, do you need to overwrite it?</source>
- <translation type="unfinished"></translation>
+ <translation>Целевой файл уже существует, вам нужно перезаписать это?</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>An error occurred during operation.</source>
- <translation type="unfinished"></translation>
+ <translation>Во время работы произошла ошибка.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/>
<source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source>
- <translation type="unfinished"></translation>
+ <translation>Пожалуйста, выберите подходящий целевой файл или файл подписи.Убедитесь, что оба находятся в этом каталоге.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
<source>No permission to read target file.</source>
- <translation type="unfinished"></translation>
+ <translation>Нет разрешения на чтение целевого файла.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
<source>No permission to read signature file.</source>
- <translation type="unfinished"></translation>
+ <translation>Нет разрешения на чтение файла подписи.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
<source>Select a file(.gpg/.asc) before doing it.</source>
- <translation type="unfinished"></translation>
+ <translation>Выберите файл (.gpg / .asc), прежде чем делать это.</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/>
- <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/>
+ <source>Outdated Version</source>
+ <translation>Устаревшая версия</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
- <source>Select a file before doing it.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/>
+ <source>This version(%1) is out of date, please update the latest version in time. </source>
+ <translation>Эта версия (% 1) устарела, пожалуйста, обновите последнюю версию вовремя.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/>
+ <source>You can download the latest version(%1) on Github Releases Page.&lt;br/&gt;</source>
+ <translation>Вы можете скачать последнюю версию (% 1) на странице выбросов GitHub. &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/>
+ <source>Unreleased Version</source>
+ <translation>Неразрешенная версия</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/>
+ <source>This version(%1) has not been officially released and is not recommended for use in a production environment. &lt;br/&gt;</source>
+ <translation>Эта версия (% 1) не была официально выпущена и не рекомендуется для использования в производственной среде.&lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/>
<source>There is one unencrypted file in attachment folder</source>
- <translation type="unfinished"></translation>
+ <translation>Есть один незашифрованный файл в папке вложения</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source>There are </source>
- <translation type="unfinished"></translation>
+ <translation>Есть</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source> unencrypted files in attachment folder</source>
- <translation type="unfinished"></translation>
+ <translation>Непритвержденные файлы в папке вложения</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="30"/>
<source>&amp;New</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Новый</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="36"/>
<source>Open a new file</source>
- <translation type="unfinished"></translation>
+ <translation>Открыть новый файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="39"/>
<source>&amp;Open...</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Открыть...</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="42"/>
<source>Open an existing file</source>
- <translation type="unfinished"></translation>
+ <translation>Откройте существующий файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="45"/>
<source>&amp;Browser</source>
- <translation type="unfinished"></translation>
+ <translation>И браузер</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="47"/>
<source>Open a file browser</source>
- <translation type="unfinished"></translation>
+ <translation>Откройте файловый браузер</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="50"/>
<source>&amp;Save</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Сохранить</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="53"/>
<source>Save the current File</source>
- <translation type="unfinished"></translation>
+ <translation>Сохранить текущий файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="56"/>
<source>Save &amp;As</source>
- <translation type="unfinished"></translation>
+ <translation>Сохранить как</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="59"/>
<source>Save the current File as...</source>
- <translation type="unfinished"></translation>
+ <translation>Сохраните текущий файл как ...</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="62"/>
<source>&amp;Print</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Распечатать</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="65"/>
<source>Print Document</source>
- <translation type="unfinished"></translation>
+ <translation>Печать документа</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="68"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Закрывать</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="70"/>
<source>Close file</source>
- <translation type="unfinished"></translation>
+ <translation>Закрыть файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="73"/>
<source>&amp;Quit</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Покидать</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="76"/>
<source>Quit Program</source>
- <translation type="unfinished"></translation>
+ <translation>Бросить программу</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="81"/>
<source>&amp;Undo</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Отменить</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="83"/>
<source>Undo Last Edit Action</source>
- <translation type="unfinished"></translation>
+ <translation>Отменить последнее редактировать действие</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="86"/>
<source>&amp;Redo</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Redo.</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="88"/>
<source>Redo Last Edit Action</source>
- <translation type="unfinished"></translation>
+ <translation>Redo Последние редактировать действие</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="91"/>
<source>Zoom In</source>
- <translation type="unfinished"></translation>
+ <translation>Увеличить</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="95"/>
<source>Zoom Out</source>
- <translation type="unfinished"></translation>
+ <translation>Уменьшить</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="99"/>
<source>&amp;Paste</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Вставить</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="102"/>
<source>Paste Text From Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Вставить текст из буфера обмена</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="105"/>
<source>Cu&amp;t</source>
- <translation type="unfinished"></translation>
+ <translation>С &amp; т.</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="108"/>
<source>Cut the current selection&apos;s contents to the clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Разрежьте содержимое текущего выбора в буфер обмена</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="112"/>
<source>&amp;Copy</source>
- <translation type="unfinished"></translation>
+ <translation>И скопируйте</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="115"/>
<source>Copy the current selection&apos;s contents to the clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>Скопируйте содержимое текущего выбора в буфер обмена</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="119"/>
<source>&amp;Quote</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; quot</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="121"/>
<source>Quote whole text</source>
- <translation type="unfinished"></translation>
+ <translation>Цитировать весь текст</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="124"/>
<source>Select &amp;All</source>
- <translation type="unfinished"></translation>
+ <translation>Выбрать все</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="127"/>
<source>Select the whole text</source>
- <translation type="unfinished"></translation>
+ <translation>Выберите весь текст</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="130"/>
<source>&amp;Find</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Находить</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="132"/>
<source>Find a word</source>
- <translation type="unfinished"></translation>
+ <translation>Найти слово</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="135"/>
<source>Remove &amp;spacing</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить и расстояние</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="138"/>
<source>Remove double linebreaks, e.g. in pasted text from webmailer</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить двойные линии, например,В вставленном тексте от Webmailer</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="141"/>
<source>Se&amp;ttings</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Tutting.</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="142"/>
<source>Open settings dialog</source>
- <translation type="unfinished"></translation>
+ <translation>Диалог открытых настроек</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="148"/>
<source>&amp;Encrypt</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Шифрование</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="151"/>
<source>Encrypt Message</source>
- <translation type="unfinished"></translation>
+ <translation>Шифрование сообщения</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="154"/>
<source>&amp;Encrypt &amp;Sign</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Шифра и подписать</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="157"/>
<source>Encrypt and Sign Message</source>
- <translation type="unfinished"></translation>
+ <translation>Зашифруйте и подписывать сообщение</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="160"/>
<source>&amp;Decrypt</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Decrypt</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="163"/>
<source>Decrypt Message</source>
- <translation type="unfinished"></translation>
+ <translation>Расшифровать сообщение</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="166"/>
<source>&amp;Decrypt &amp;Verify</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Decrypt &amp; проверить</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="169"/>
<source>Decrypt and Verify Message</source>
- <translation type="unfinished"></translation>
+ <translation>Расшифровать и проверить сообщение</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="175"/>
<source>&amp;Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Зашифруйте файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="176"/>
<source>Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Зашифруйте файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="179"/>
<source>&amp;Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Дешифративный файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="180"/>
<source>Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>Дешифративный файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="183"/>
<source>&amp;Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp; Знак файла</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="184"/>
<source>Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>Знак файла</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="187"/>
<source>&amp;Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>И проверить файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="188"/>
<source>Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>Проверьте файл</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="192"/>
<source>&amp;Sign</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Знак</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="195"/>
<source>Sign Message</source>
- <translation type="unfinished"></translation>
+ <translation>Знак сообщения</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="198"/>
<source>&amp;Verify</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Проверять</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="201"/>
<source>Verify Message</source>
- <translation type="unfinished"></translation>
+ <translation>Проверить сообщение</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="207"/>
<source>&amp;Editor</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Редактор</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="209"/>
<source>Import New Key From Editor</source>
- <translation type="unfinished"></translation>
+ <translation>Импортировать новый ключ от редактора</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/>
- <source>Manage &amp;keys</source>
- <translation type="unfinished"></translation>
+ <source>Manage &amp;Keys</source>
+ <translation>Управление и клавиши</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="214"/>
<source>Open Keymanagement</source>
- <translation type="unfinished"></translation>
+ <translation>Открыть ключманагемент</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/>
<source>&amp;About</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;О</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/>
<source>Show the application&apos;s About box</source>
- <translation type="unfinished"></translation>
+ <translation>Показать приложение о коробке</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/>
+ <source>&amp;Check for Updates</source>
+ <translation>Проверьте наличие обновлений</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <source>Check for updates</source>
+ <translation>Проверьте наличие обновлений</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/>
<source>Open &amp;Wizard</source>
- <translation type="unfinished"></translation>
+ <translation>Open &amp; Wizard</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
<source>Open the wizard</source>
- <translation type="unfinished"></translation>
+ <translation>Откройте волшебник</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
<source>Append Selected Key(s) To Text</source>
- <translation type="unfinished"></translation>
+ <translation>Добавьте выбранные ключи в текст</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
<source>Append The Selected Keys To Text in Editor</source>
- <translation type="unfinished"></translation>
+ <translation>Добавьте выбранные ключи в текст в редакторе</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
- <source>Copy EMail-address</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <source>Copy Email</source>
+ <translation>Скопируйте электронную почту</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/>
- <source>Copy selected EMailaddress to clipboard</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <source>Copy selected Email to clipboard</source>
+ <translation>Скопируйте выбранную электронную почту в буфер обмена</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
<source>Show Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>Показать ключевые детали</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/>
<source>Show Details for this Key</source>
- <translation type="unfinished"></translation>
+ <translation>Показать детали для этого ключа</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/>
<source>Refresh Key From Key Server</source>
- <translation type="unfinished"></translation>
+ <translation>Обновить ключ от ключевого сервера</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/>
<source>Refresh key from default key server</source>
- <translation type="unfinished"></translation>
+ <translation>Обновить ключ с сервера ключей по умолчанию</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/>
<source>Upload Public Key(s) To Server</source>
- <translation type="unfinished"></translation>
+ <translation>Загрузить открытый ключ (ы) на сервер</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/>
<source>Upload The Selected Public Keys To Server</source>
- <translation type="unfinished"></translation>
+ <translation>Загрузить выбранные открытые клавиши на сервер</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/>
<source>Remove PGP Header</source>
- <translation type="unfinished"></translation>
+ <translation>Удалить заголовок PGP</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/>
<source>Add PGP Header</source>
- <translation type="unfinished"></translation>
+ <translation>Добавить PGP заголовок</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/>
<source>&amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Файл</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/>
<source>&amp;Edit</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Редактировать</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/>
<source>&amp;File...</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Файл...</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/>
<source>&amp;Crypt</source>
- <translation type="unfinished"></translation>
+ <translation>И склеил</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
<source>&amp;Keys</source>
- <translation type="unfinished"></translation>
+ <translation>И ключи</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/>
<source>&amp;Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>И Импорт ключ</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/>
<source>&amp;Steganography</source>
- <translation type="unfinished"></translation>
+ <translation>Стеганография</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
<source>&amp;View</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Вид</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/>
<source>&amp;Help</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Помощь</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/>
<source>File</source>
- <translation type="unfinished"></translation>
+ <translation>Файл</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/>
<source>Crypt</source>
- <translation type="unfinished"></translation>
+ <translation>Крипта</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/>
<source>Key</source>
- <translation type="unfinished"></translation>
+ <translation>Ключ</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/>
<source>Edit</source>
- <translation type="unfinished"></translation>
+ <translation>Редактировать</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/>
<source>Special Edit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/>
<source>Import key from...</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт ключ от ...</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/>
<source>Import key</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт ключ</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/>
<source>Browser to view and operate file</source>
- <translation type="unfinished"></translation>
+ <translation>Браузер для просмотра и управления файлом</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/>
<source>Browser</source>
- <translation type="unfinished"></translation>
+ <translation>Браузер</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/>
<source>Ready</source>
- <translation type="unfinished"></translation>
+ <translation>Готовый</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/>
<source>Key ToolBox</source>
- <translation type="unfinished"></translation>
+ <translation>Ключевой набор инструментов</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/>
<source>Information Board</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/>
- <source>Attached files:</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>MimeTab</name>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
- <source>Decode quoted printable</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="292"/>
- <source>Try to recognize quoted printable.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="296"/>
- <source>Parse PGP/MIME (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="299"/>
- <source>Try to split attachments from PGP-MIME ecrypted messages.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="304"/>
- <source>Open with external application (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="306"/>
- <source>Open attachments with default application for the filetype.&lt;br&gt; There are at least two possible problems with this behaviour:&lt;ol&gt;&lt;li&gt;File needs to be saved unencrypted to attachments folder.&lt;br&gt; Its your job to clean this folder.&lt;/li&gt;&lt;li&gt;The external application may have its own temp files.&lt;/li&gt;&lt;/ol&gt;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
- <source>Enable opening with external applications.</source>
- <translation type="unfinished"></translation>
+ <translation>Доска объявлений</translation>
</message>
</context>
<context>
@@ -2664,107 +2801,107 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/gpg/result_analyse/DecryptResultAnalyse.cpp" line="42"/>
<source>&gt;Recipient: </source>
- <translation type="unfinished"></translation>
+ <translation>&gt; Получатель:</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="35"/>
<source>One or More Bad Signatures.</source>
- <translation type="unfinished"></translation>
+ <translation>Одна или несколько плохих подписей.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="40"/>
<source>A </source>
- <translation type="unfinished"></translation>
+ <translation>А.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="42"/>
<source>Good </source>
- <translation type="unfinished"></translation>
+ <translation>Хорошо</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="45"/>
<source>Bad </source>
- <translation type="unfinished"></translation>
+ <translation>Плохо</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="48"/>
<source>Expired </source>
- <translation type="unfinished"></translation>
+ <translation>Истекший</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="51"/>
<source>Missing Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>Отсутствует ключ</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="54"/>
<source>Revoked Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>Отменил ключ</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="57"/>
<source>Expired Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>Истекший ключ</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="60"/>
<source>Missing CRL&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>Отсутствие CRL&apos;s.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="64"/>
<source>Signature Fully Valid.</source>
- <translation type="unfinished"></translation>
+ <translation>Подпись полностью действительна.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="66"/>
<source>Signature NOT Fully Valid.</source>
- <translation type="unfinished"></translation>
+ <translation>Подпись не полностью действительна.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="74"/>
<source>Key is NOT present with ID 0x</source>
- <translation type="unfinished"></translation>
+ <translation>Ключ отсутствует с ID 0x</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="81"/>
<source>A signature could NOT be verified due to a Missing Key
</source>
- <translation type="unfinished"></translation>
+ <translation>Подпись не может быть проверена из-за недостающего ключа</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="85"/>
<source>A signature is valid but the key used to verify the signature has been revoked
</source>
- <translation type="unfinished"></translation>
+ <translation>Подпись действительна, но ключ, используемый для проверки подписи, был отменен</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="93"/>
<source>A signature is valid but expired
</source>
- <translation type="unfinished"></translation>
+ <translation>Подпись действительна, но истек</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="100"/>
<source>A signature is valid but the key used to verify the signature has expired.
</source>
- <translation type="unfinished"></translation>
+ <translation>Подпись действительна, но ключ, используемый для проверки подписи, истек.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="107"/>
<source>There was some other error which prevented the signature verification.
</source>
- <translation type="unfinished"></translation>
+ <translation>Была какая-то другая ошибка, которая предотвратила проверку подписи.</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="113"/>
<source>Error for key with fingerprint </source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка для ключа с отпечатками пальца</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="128"/>
<source>Signed By: </source>
- <translation type="unfinished"></translation>
+ <translation>Подписано:</translation>
</message>
</context>
<context>
@@ -2772,60 +2909,193 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="29"/>
<source>Unsaved Files</source>
- <translation type="unfinished"></translation>
+ <translation>Несохраненные файлы</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="77"/>
- <source>&lt;h3&gt;%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?&lt;/h3&gt;</source>
- <translation type="unfinished"></translation>
+ <source>%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?</source>
+ <translation>Файлы% 1 содержат несохраненную информацию. &lt;br/&gt; Сохранить изменения перед закрытием?</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="88"/>
<source>Check the files you want to save:</source>
- <translation type="unfinished"></translation>
+ <translation>Проверьте файлы, которые вы хотите сохранить:</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="89"/>
<source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;b&gt; Примечание: &lt;/ b&gt; Если вы не сохраните эти файлы, все изменения потеряны. &lt;br/&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>SendMailDialog</name>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="35"/>
+ <source>Incomplete configuration</source>
+ <translation>Неполная конфигурация</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="36"/>
+ <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source>
+ <translation>Адрес SMTP пуст, перейдите на интерфейс настройки, чтобы завершить конфигурацию.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="86"/>
+ <source> Recipient cannot be empty
+</source>
+ <translation>Получатель не может быть пустым</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="91"/>
+ <source> One or more Recipient&apos;s Email Address is invalid
+</source>
+ <translation>Один или несколько адресов электронной почты получателя недействителен</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="97"/>
+ <source> Sender cannot be empty
+</source>
+ <translation>Отправитель не может быть пустым</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="99"/>
+ <source> Sender&apos;s Email Address is invalid
+</source>
+ <translation>Адрес электронной почты отправителя недействителен</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail</source>
+ <translation>Неудача</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation>Не удается подключить SMTP-сервер</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <source>Fail to Login into SMTP Server</source>
+ <translation>Не входить в систему на SMTP-сервер</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail to Send Mail to SMTP Server</source>
+ <translation>Не удалось отправить почту на SMTP-сервер</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Success</source>
+ <translation>Успех</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Succeed in Sending Mail to SMTP Server</source>
+ <translation>Успешно отправлять почту на SMTP-сервер</translation>
+ </message>
+</context>
+<context>
+ <name>SendMailTab</name>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
+ <source>Enable</source>
+ <translation>Давать возможность</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="311"/>
+ <source>SMTP Address</source>
+ <translation>SMTP-адрес</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="313"/>
+ <source>Username</source>
+ <translation>Имя пользователя</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
+ <source>Password</source>
+ <translation>Пароль</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="317"/>
+ <source>Port</source>
+ <translation>Порт</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="319"/>
+ <source>Connection Security</source>
+ <translation>Безопасность подключения</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="322"/>
+ <source>Default Sender</source>
+ <translation>Отправитель по умолчанию</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail</source>
+ <translation>Неудача</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation>Не удается подключить SMTP-сервер</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail to Login</source>
+ <translation>Не входить в систему</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Success</source>
+ <translation>Успех</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Succeed in connecting and login</source>
+ <translation>Преуспеть в подключении и входе в систему</translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="38"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
<source>General</source>
- <translation type="unfinished"></translation>
+ <translation>Общий</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="39"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
<source>Appearance</source>
- <translation type="unfinished"></translation>
+ <translation>Появление</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
- <source>PGP/Mime</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="42"/>
+ <source>Send Mail</source>
+ <translation>Отправить почту</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
<source>Key Server</source>
- <translation type="unfinished"></translation>
+ <translation>Ключевой сервер</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="45"/>
<source>Advanced</source>
- <translation type="unfinished"></translation>
+ <translation>Передовой</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="56"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="58"/>
<source>Settings</source>
- <translation type="unfinished"></translation>
+ <translation>Настройки</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="101"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="103"/>
<source>System Default</source>
- <translation type="unfinished"></translation>
+ <translation>Системные установки по умолчанию</translation>
</message>
</context>
<context>
@@ -2833,62 +3103,62 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="46"/>
<source>Generate New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>Генерировать новый подразделение</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="61"/>
<source>Encryption</source>
- <translation type="unfinished"></translation>
+ <translation>Шифрование</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="64"/>
<source>Signing</source>
- <translation type="unfinished"></translation>
+ <translation>Подписание</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="67"/>
<source>Certification</source>
- <translation type="unfinished"></translation>
+ <translation>Сертификация</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="70"/>
<source>Authentication</source>
- <translation type="unfinished"></translation>
+ <translation>Аутентификация</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="114"/>
<source>Expiration Date:</source>
- <translation type="unfinished"></translation>
+ <translation>Дата окончания срока:</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="115"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>Никогда не истекаешь</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="116"/>
<source>KeySize (in Bit):</source>
- <translation type="unfinished"></translation>
+ <translation>Клинизировать (по-бит):</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="117"/>
<source>Key Type:</source>
- <translation type="unfinished"></translation>
+ <translation>Тип ключа:</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="126"/>
<source>Basic Information</source>
- <translation type="unfinished"></translation>
+ <translation>Основная информация</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="214"/>
<source> Expiration time no more than 2 years. </source>
- <translation type="unfinished"></translation>
+ <translation>Время истечения не более 2 лет.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="235"/>
<source>Generating Subkey...</source>
- <translation type="unfinished"></translation>
+ <translation>Генерация подраздела ...</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="238"/>
@@ -2896,90 +3166,129 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
This may take a while.
To speed up the process use your computer
(e.g. browse the net, listen to music,...)</source>
- <translation type="unfinished"></translation>
+ <translation>Сбор случайных данных для поколения подраздела.
+ Это может занять некоторое время.
+ Чтобы ускорить процесс, используйте свой компьютер
+ (например, просмотрите чистую, слушаю музыку, ...)</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/>
<source>Success</source>
- <translation type="unfinished"></translation>
+ <translation>Успех</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/>
<source>The new subkey has been generated.</source>
- <translation type="unfinished"></translation>
+ <translation>Новый подразделение было сгенерировано.</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/>
<source>Failure</source>
- <translation type="unfinished"></translation>
+ <translation>Отказ</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/>
<source>An error occurred during subkey generation.</source>
- <translation type="unfinished"></translation>
+ <translation>Произошла ошибка во время поколения подраздела.</translation>
</message>
</context>
<context>
<name>TextEdit</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/>
<source>untitled</source>
- <translation type="unfinished"></translation>
+ <translation>Безватый</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>Предупреждение</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/>
+ <source>Cannot read file %1:
+%2.</source>
+ <translation>Не удается прочитать файл% 1:
+% 2.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/>
<source>Open file</source>
- <translation type="unfinished"></translation>
+ <translation>Открыть файл</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/>
+ <source>File</source>
+ <translation>Файл</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/>
+ <source>Cannot write file %1:
+%2.</source>
+ <translation>Невозможно написать файл% 1:
+% 2.</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
<source>Save file</source>
- <translation type="unfinished"></translation>
+ <translation>Сохранить файл</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/>
+ <source>Unsaved document</source>
+ <translation>Несохраненный документ</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/>
+ <source>The document &quot;%1&quot; has been modified. Do you want to save your changes?&lt;br/&gt;</source>
+ <translation>Документ «% 1» был изменен.Вы хотите сохранить ваши изменения? &lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/>
+ <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
+ <translation>&lt;b&gt; Примечание: &lt;/ b&gt; Если вы не сохраните эти файлы, все изменения потеряны. &lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/>
<source>Application</source>
- <translation type="unfinished"></translation>
+ <translation>Заявление</translation>
</message>
+</context>
+<context>
+ <name>UpdateTab</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/>
- <source>Cannot read file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/>
+ <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source>
+ <translation>Рекомендуется, чтобы вы всегда проверяли версию GPGFRontend и обновите до последней версии.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/>
- <source>File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/>
+ <source>New versions not only represent new features, but also often represent functional and security fixes.</source>
+ <translation>Новые версии не только представляют новые функции, но и часто представляют функциональные и безопасные исправления.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/>
- <source>Cannot write file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/>
+ <source>Current Version: </source>
+ <translation>Текущая версия:</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/>
- <source>Unsaved document</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/>
+ <source>The current version is inconsistent with the latest version on github.</source>
+ <translation>Текущая версия несовместима с последней версией на Github.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/>
- <source>&lt;h3&gt;The document &quot;%1&quot; has been modified.&lt;br/&gt;Do you want to save your changes?&lt;/h3&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/>
+ <source>Please click &lt;a href=&quot;https://github.com/saturneric/GpgFrontend/releases&quot;&gt;here&lt;/a&gt; to download the latest version.</source>
+ <translation>Пожалуйста, нажмите &lt;a href=&quot;http://github.com/saturneric/gpgfrontend/relestrestions&quot;&gt; Здесь &lt;/a&gt; для загрузки последней версии.</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
- <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/>
+ <source>Latest Version From Github: </source>
+ <translation>Последняя версия из GitHub:</translation>
</message>
</context>
<context>
@@ -2987,32 +3296,32 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="32"/>
<source>Signature Details</source>
- <translation type="unfinished"></translation>
+ <translation>Подробности подписи</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="53"/>
<source>Status: </source>
- <translation type="unfinished"></translation>
+ <translation>Статус:</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="56"/>
<source>No valid input found</source>
- <translation type="unfinished"></translation>
+ <translation>Допустимый вход не найден</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="67"/>
<source>Error Validating signature</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка проверки подписи</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="70"/>
<source>File was signed on %1 &lt;br/&gt; It Contains:&lt;br/&gt;&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Файл был подписан на% 1 &lt;br/&gt; он содержит: &lt;br/&gt; &lt;br/&gt;</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="72"/>
<source>Signed on %1 &lt;br/&gt; It Contains:&lt;br /&gt;&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>Подписано на% 1 &lt;br/&gt; Он содержит: &lt;br /&gt; &lt;br/&gt;</translation>
</message>
</context>
<context>
@@ -3020,22 +3329,22 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="36"/>
<source>Import from keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>Импорт от Keyserver</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="39"/>
<source>Key not present with id 0x</source>
- <translation type="unfinished"></translation>
+ <translation>Ключ не присутствует с ID 0x</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="43"/>
<source>Status:</source>
- <translation type="unfinished"></translation>
+ <translation>Статус:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="45"/>
<source>Key not present in keylist</source>
- <translation type="unfinished"></translation>
+ <translation>Ключ не присутствует в кейлисте</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="58"/>
@@ -3045,7 +3354,7 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="115"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="129"/>
<source>Key Information is NOT Available</source>
- <translation type="unfinished"></translation>
+ <translation>Основная информация недоступна</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="60"/>
@@ -3055,103 +3364,103 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="117"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="131"/>
<source>Fingerprint: </source>
- <translation type="unfinished"></translation>
+ <translation>Отпечаток пальца:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="67"/>
<source>Status: Cert Revoked</source>
- <translation type="unfinished"></translation>
+ <translation>Статус: Сертинг отозван</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="81"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="95"/>
<source>Status: Signature Expired</source>
- <translation type="unfinished"></translation>
+ <translation>Статус: подпись истек</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="96"/>
<source>Status: Key Expired</source>
- <translation type="unfinished"></translation>
+ <translation>Статус: ключ истек</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="110"/>
<source>Status: General Error</source>
- <translation type="unfinished"></translation>
+ <translation>Статус: общая ошибка</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="124"/>
<source>Status: Unknown Error</source>
- <translation type="unfinished"></translation>
+ <translation>Статус: неизвестная ошибка</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="159"/>
<source>Signer Name:</source>
- <translation type="unfinished"></translation>
+ <translation>Название сигнала:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="160"/>
<source>Signer Email:</source>
- <translation type="unfinished"></translation>
+ <translation>Email Signer Email:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="161"/>
<source>Key&apos;s Fingerprint:</source>
- <translation type="unfinished"></translation>
+ <translation>Отпечаток ключа:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="162"/>
<source>Valid:</source>
- <translation type="unfinished"></translation>
+ <translation>Действительный:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="163"/>
<source>Flags:</source>
- <translation type="unfinished"></translation>
+ <translation>Флаги:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="171"/>
<source>Fully Valid</source>
- <translation type="unfinished"></translation>
+ <translation>Полностью действителен</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="173"/>
<source>NOT Fully Valid</source>
- <translation type="unfinished"></translation>
+ <translation>Не полностью действительным</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="180"/>
<source>Good </source>
- <translation type="unfinished"></translation>
+ <translation>Хорошо</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="183"/>
<source>Bad </source>
- <translation type="unfinished"></translation>
+ <translation>Плохо</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="186"/>
<source>Expired </source>
- <translation type="unfinished"></translation>
+ <translation>Истекший</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="189"/>
<source>Missing Key </source>
- <translation type="unfinished"></translation>
+ <translation>Пропавший ключ</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="192"/>
<source>Revoked Key </source>
- <translation type="unfinished"></translation>
+ <translation>Отменил ключ</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="195"/>
<source>Expired Key </source>
- <translation type="unfinished"></translation>
+ <translation>Ключ срок действия</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="198"/>
<source>Missing CRL </source>
- <translation type="unfinished"></translation>
+ <translation>Пропавший CRL</translation>
</message>
</context>
<context>
@@ -3159,33 +3468,33 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/Wizard.cpp" line="46"/>
<source>First Start Wizard</source>
- <translation type="unfinished"></translation>
+ <translation>Первый запуск волшебника</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="76"/>
<source>Import Error</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка импорта</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="76"/>
<source>Couldn&apos;t locate any keyring file in %1</source>
- <translation type="unfinished"></translation>
+ <translation>Не мог найти любой файл ключа в% 1</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="84"/>
<location filename="../../src/ui/Wizard.cpp" line="95"/>
<source>Import error</source>
- <translation type="unfinished"></translation>
+ <translation>Ошибка импорта</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="85"/>
<source>Couldn&apos;t open private keyringfile: %1</source>
- <translation type="unfinished"></translation>
+ <translation>Не мог открыть частное cliedingfile:% 1</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="96"/>
<source>Couldn&apos;t open public keyringfile: %1</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось открыть открытый клавиатуре:% 1</translation>
</message>
</context>
</TS>
diff --git a/resource/ts/gpgfrontend_zh_chs.ts b/resource/ts/gpgfrontend_zh_cn.ts
index 7bf4bd62..58efd923 100644
--- a/resource/ts/gpgfrontend_zh_chs.ts
+++ b/resource/ts/gpgfrontend_zh_cn.ts
@@ -4,212 +4,197 @@
<context>
<name>AboutDialog</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="29"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/>
<source>About </source>
- <translation type="unfinished"></translation>
+ <translation>关于</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="35"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/>
<source>General</source>
- <translation type="unfinished"></translation>
+ <translation>通用</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="36"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/>
<source>Translators</source>
- <translation type="unfinished"></translation>
+ <translation>译者</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/>
+ <source>Update</source>
+ <translation>更新</translation>
</message>
</context>
<context>
<name>AdvancedTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="580"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="679"/>
<source>Show Steganography Options [Advanced]</source>
- <translation type="unfinished"></translation>
+ <translation>显示隐写术选项[高级]</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="582"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="681"/>
<source>Show Steganographic Options.</source>
- <translation type="unfinished"></translation>
+ <translation>显示隐写术选项。</translation>
</message>
</context>
<context>
<name>AppearanceTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="368"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="444"/>
<source>Iconsize</source>
- <translation type="unfinished"></translation>
+ <translation>图标化</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="370"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="446"/>
<source>small</source>
- <translation type="unfinished"></translation>
+ <translation>小的</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="371"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="447"/>
<source>medium</source>
- <translation type="unfinished"></translation>
+ <translation>中等的</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="372"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="448"/>
<source>large</source>
- <translation type="unfinished"></translation>
+ <translation>大</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="388"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="464"/>
<source>Iconstyle</source>
- <translation type="unfinished"></translation>
+ <translation>图标样式</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="390"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="466"/>
<source>just text</source>
- <translation type="unfinished"></translation>
+ <translation>只是文字</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="391"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="467"/>
<source>just icons</source>
- <translation type="unfinished"></translation>
+ <translation>只是图标</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="392"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="468"/>
<source>text and icons</source>
- <translation type="unfinished"></translation>
+ <translation>文字和图标</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="484"/>
<source>Windowstate</source>
- <translation type="unfinished"></translation>
+ <translation>窗口状态</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="411"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="487"/>
<source>Save window size and position on exit.</source>
- <translation type="unfinished"></translation>
+ <translation>保存窗口大小和位置。</translation>
</message>
-</context>
-<context>
- <name>AttachmentTableModel</name>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/>
- <source>Filename</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="495"/>
+ <source>Information Board</source>
+ <translation>信息板</translation>
</message>
<message>
- <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/>
- <source>Contenttype</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="501"/>
+ <source> Front Size</source>
+ <translation>字体大小</translation>
</message>
</context>
<context>
- <name>Attachments</name>
+ <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/>
- <source>Save File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="165"/>
+ <source>Choose your action...</source>
+ <translation>选择你的行动......</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/>
- <source>Save this file</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="166"/>
+ <source>...by clicking on the appropriate link.</source>
+ <translation>...单击相应的链接。</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/>
- <source>Open File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="168"/>
+ <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
+ <translation>如果您之前从未使用过GPG2Rend并且也没有拥有GPG密钥,但您可能希望阅读如何</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/>
- <source>Open this file</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="170"/>
+ <source>Generate Key</source>
+ <translation>生成密钥对</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/>
- <source>File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="176"/>
+ <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source>
+ <translation>如果您想了解如何加密,解密,签名和验证文本,可以阅读</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/>
- <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/>
- <source>Cannot write file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <source>Encrypt &amp; Decrypt Text</source>
+ <translation>加密&amp;解密文本</translation>
</message>
-</context>
-<context>
- <name>ChoosePage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="161"/>
- <source>Choose your action...</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="178"/>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>or</source>
+ <translation>或者</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="162"/>
- <source>...by clicking on the appropriate link.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="180"/>
+ <source>Sign &amp; Verify Text</source>
+ <translation>签名&amp;验证文本</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="164"/>
- <source>If you have never used GPGFrontend before and also don&apos;t own a gpg key yet you may possibly want to read how to</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="188"/>
+ <source>If you want to operate file, you can read </source>
+ <translation>如果要操作文件,可以阅读</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="172"/>
- <source>If you want to learn how to encrypt and decrypt text, you can read </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="190"/>
+ <source>Encrypt &amp; Sign File</source>
+ <translation>加密&amp;签名文件</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="174"/>
- <location filename="../../src/ui/Wizard.cpp" line="183"/>
- <source>this document</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/Wizard.cpp" line="181"/>
- <source>If you want to sign and verify text, you can read </source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/Wizard.cpp" line="166"/>
- <source>create a new keypair</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/Wizard.cpp" line="192"/>
+ <source>Sign &amp; Verify File</source>
+ <translation>签名&amp;验证文件</translation>
</message>
</context>
<context>
<name>ConclusionPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="397"/>
+ <location filename="../../src/ui/Wizard.cpp" line="407"/>
<source>Ready.</source>
- <translation type="unfinished"></translation>
+ <translation>准备好。</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="398"/>
+ <location filename="../../src/ui/Wizard.cpp" line="408"/>
<source>Have fun with GPGFrontend!</source>
- <translation type="unfinished"></translation>
+ <translation>在GPGFrontend玩得开心!</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="400"/>
+ <location filename="../../src/ui/Wizard.cpp" line="410"/>
<source>You are ready to use GPGFrontend now.&lt;br&gt;&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>你现在准备好使用GPGFrontend。&lt;br&gt; &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="402"/>
+ <location filename="../../src/ui/Wizard.cpp" line="412"/>
<source>The Online Document</source>
- <translation type="unfinished"></translation>
+ <translation>在线文档</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="403"/>
+ <location filename="../../src/ui/Wizard.cpp" line="413"/>
<source> will get you started with GPGFrontend. It will open in the main window.&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>会带领你开始使用GPGFrontend。它将在主窗口中打开。&lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="410"/>
+ <location filename="../../src/ui/Wizard.cpp" line="420"/>
<source>Open offline help.</source>
- <translation type="unfinished"></translation>
+ <translation>打开离线帮助。</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="413"/>
+ <location filename="../../src/ui/Wizard.cpp" line="423"/>
<source>Dont show the wizard again.</source>
- <translation type="unfinished"></translation>
+ <translation>不要再次显示向导。</translation>
</message>
</context>
<context>
@@ -217,129 +202,152 @@
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="32"/>
<source>Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>解密文件</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="34"/>
<source>Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>加密文件</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="36"/>
<source>Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>签名文件</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="38"/>
<source>Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>验证文件</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="47"/>
<source>Input Parameters</source>
- <translation type="unfinished"></translation>
+ <translation>输入参数</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="53"/>
<source>Target File</source>
- <translation type="unfinished"></translation>
+ <translation>目标文件</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="59"/>
<source>Output File</source>
- <translation type="unfinished"></translation>
+ <translation>输出文件</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="75"/>
<source>Signature File(.sig) Path</source>
- <translation type="unfinished"></translation>
+ <translation>签名文件(.sig)路径</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="134"/>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="177"/>
<source>Open File</source>
- <translation type="unfinished"></translation>
+ <translation>打开文件</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="165"/>
<source>Save File</source>
- <translation type="unfinished"></translation>
+ <translation>保存存档</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
<source>Couldn&apos;t open file</source>
- <translation type="unfinished"></translation>
+ <translation>无法打开文件</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/>
+ <source>Error</source>
+ <translation>错误</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/>
+ <source>Error Occurred During Encryption</source>
+ <translation>加密期间发生错误</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/>
+ <source>Error Occurred During Decryption</source>
+ <translation>解密期间发生错误</translation>
</message>
<message>
<location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/>
+ <source>Error Occurred During Signature</source>
+ <translation>签名期间发生错误</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/>
<source>File</source>
- <translation type="unfinished"></translation>
+ <translation>文件</translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/>
<source>File exists! Do you want to overwrite it?</source>
- <translation type="unfinished"></translation>
+ <translation>文件已存在!你想覆盖它吗?</translation>
</message>
<message>
- <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/>
+ <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/>
<source>Cannot write file %1:
%2.</source>
- <translation type="unfinished"></translation>
+ <translation>无法写入文件%1:
+%2。</translation>
</message>
</context>
<context>
<name>FilePage</name>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/>
<source>Open</source>
- <translation type="unfinished"></translation>
+ <translation>打开</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/>
<source>Delete</source>
- <translation type="unfinished"></translation>
+ <translation>删除</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/>
<source>Encrypt and Sign</source>
- <translation type="unfinished"></translation>
+ <translation>加密和签名</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/>
<source>Decrypt and Verify</source>
- <translation type="unfinished"></translation>
+ <translation>解密和验证</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/>
<source>Only Sign</source>
- <translation type="unfinished"></translation>
+ <translation>只签名</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/>
<source>Only Verify</source>
- <translation type="unfinished"></translation>
+ <translation>只验证</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>警告</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/>
<source>Are you sure you want to delete it?</source>
- <translation type="unfinished"></translation>
+ <translation>你确定你要删除它?</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/>
<source>Error</source>
- <translation type="unfinished"></translation>
+ <translation>错误</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/>
+ <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/>
<source>Unable to delete the file or folder.</source>
- <translation type="unfinished"></translation>
+ <translation>无法删除文件或文件夹。</translation>
</message>
</context>
<context>
@@ -347,266 +355,281 @@
<message>
<location filename="../../src/ui/FindWidget.cpp" line="38"/>
<source>Find:</source>
- <translation type="unfinished"></translation>
+ <translation>查找:</translation>
</message>
</context>
<context>
<name>GeneralTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="135"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="137"/>
<source>Remember Password</source>
- <translation type="unfinished"></translation>
+ <translation>记住密码</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="138"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="140"/>
<source>Remember password until closing gpg4usb</source>
- <translation type="unfinished"></translation>
+ <translation>记住密码,直到关闭GPG4USB</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="145"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="147"/>
<source>Save Checked Keys</source>
- <translation type="unfinished"></translation>
+ <translation>保存选中密钥</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="148"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="150"/>
<source>Save checked private keys on exit and restore them on next start.</source>
- <translation type="unfinished"></translation>
+ <translation>在退出时保存已选中的密钥对并在下次启动时恢复。</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="157"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="159"/>
<source>Confirm drag&apos;n&apos;drop key import</source>
- <translation type="unfinished"></translation>
+ <translation>默认拖拽文件&apos;触发密钥导入</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="162"/>
<source>Import files dropped on the keylist without confirmation.</source>
- <translation type="unfinished"></translation>
+ <translation>无需确认导入文件是否要在密钥列表中显示。</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="167"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="169"/>
<source>Language</source>
- <translation type="unfinished"></translation>
+ <translation>语言</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="176"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="178"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; GpgFrontend will restart automatically if you change the language!</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;b&gt;注意:如果更改语言,则会自动重启!</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="185"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="187"/>
<source>Own key</source>
- <translation type="unfinished"></translation>
+ <translation>我的密钥</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="193"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="195"/>
<source>&lt;none&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;无&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="207"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="209"/>
<source>Key pair for synchronization and identity authentication</source>
- <translation type="unfinished"></translation>
+ <translation>用于同步和身份验证的密钥对</translation>
</message>
</context>
<context>
<name>GpgME::GpgContext</name>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="90"/>
- <source>ENV Loading Failed</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="91"/>
- <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/gpg/GpgContext.cpp" line="577"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="528"/>
<source>Wrong password</source>
- <translation type="unfinished"></translation>
+ <translation>密码错误</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="585"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="536"/>
<source>Enter Password for</source>
- <translation type="unfinished"></translation>
+ <translation>输入密码</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="589"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="540"/>
<source>Enter Password</source>
- <translation type="unfinished"></translation>
+ <translation>输入密码</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>Key Selection</source>
- <translation type="unfinished"></translation>
+ <translation>密钥选择</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="764"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="706"/>
<source>No Private Key Selected</source>
- <translation type="unfinished"></translation>
+ <translation>没有选择私钥</translation>
</message>
<message>
- <location filename="../../src/gpg/GpgContext.cpp" line="804"/>
+ <location filename="../../src/gpg/GpgContext.cpp" line="746"/>
<source>Error in signing:</source>
- <translation type="unfinished"></translation>
+ <translation>签名时出错:</translation>
</message>
</context>
<context>
<name>GpgPathsTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="612"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="711"/>
<source>Relative path to keydb</source>
- <translation type="unfinished"></translation>
+ <translation>keydB的相对路径</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="625"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="724"/>
<source>Current keydb path: </source>
- <translation type="unfinished"></translation>
+ <translation>当前密钥数据库路径:</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="630"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="729"/>
<source>&lt;b&gt;NOTE: &lt;/b&gt; Gpg4usb will restart automatically if you change the keydb path!</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;b&gt;注意:如果更改密钥数据库路径,则会自动重启!</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="659"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="758"/>
<source>Choose keydb directory</source>
- <translation type="unfinished"></translation>
+ <translation>选择密钥数据库目录</translation>
</message>
</context>
<context>
<name>ImportFromGnupgPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="292"/>
+ <location filename="../../src/ui/Wizard.cpp" line="302"/>
<source>Import keys...</source>
- <translation type="unfinished"></translation>
+ <translation>导入密钥......</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="293"/>
+ <location filename="../../src/ui/Wizard.cpp" line="303"/>
<source>...from existing GnuPG installation</source>
- <translation type="unfinished"></translation>
+ <translation>...从现有的Gnupg安装</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="295"/>
+ <location filename="../../src/ui/Wizard.cpp" line="305"/>
<source>You can import keys from a locally installed GnuPG.&lt;br&gt;&lt;br&gt; The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.&lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>您可以从本地安装的gnupg导入密钥。&lt;br&gt; &lt;br&gt;从Windows中的Registry读取位置,也可以在Linux中的主目录中假定为.gnupg文件夹。&lt;br&gt; &lt;br&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="299"/>
+ <location filename="../../src/ui/Wizard.cpp" line="309"/>
<source>Import keys from GnuPG</source>
- <translation type="unfinished"></translation>
+ <translation>从Gnupg导入密钥</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Import Error</source>
- <translation type="unfinished"></translation>
+ <translation>导入错误</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="313"/>
+ <location filename="../../src/ui/Wizard.cpp" line="323"/>
<source>Couldn&apos;t locate GnuPG home directory</source>
- <translation type="unfinished"></translation>
+ <translation>无法找到gnupg主目录</translation>
</message>
</context>
<context>
<name>ImportFromGpg4usbPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="215"/>
+ <location filename="../../src/ui/Wizard.cpp" line="225"/>
<source>Import from...</source>
- <translation type="unfinished"></translation>
+ <translation>导入于...</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="216"/>
+ <location filename="../../src/ui/Wizard.cpp" line="226"/>
<source>...existing GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>......现有的GPGFrontend.</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="218"/>
+ <location filename="../../src/ui/Wizard.cpp" line="228"/>
<source>You can import keys and/or settings from existing GPGFrontend. &lt;br&gt;&lt;br&gt;Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source>
- <translation type="unfinished"></translation>
+ <translation>您可以从现有GPGFrontend导入密钥和/或设置。&lt;br&gt; &lt;br&gt;查看要导入的内容,单击“导入”按钮,然后在“出现的文件”对话框中选择其他GPGFrontend的目录。</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="225"/>
+ <location filename="../../src/ui/Wizard.cpp" line="235"/>
<source>Keys</source>
- <translation type="unfinished"></translation>
+ <translation>密钥</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="229"/>
+ <location filename="../../src/ui/Wizard.cpp" line="239"/>
<source>Configuration</source>
- <translation type="unfinished"></translation>
+ <translation>配置</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="231"/>
+ <location filename="../../src/ui/Wizard.cpp" line="241"/>
<source>Import from GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>从GPGFrontend导入</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="246"/>
+ <location filename="../../src/ui/Wizard.cpp" line="256"/>
<source>Other GPGFrontend directory</source>
- <translation type="unfinished"></translation>
+ <translation>其他GPGFrontend目录</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="265"/>
+ <location filename="../../src/ui/Wizard.cpp" line="275"/>
<source>Configuration Imported</source>
- <translation type="unfinished"></translation>
+ <translation>配置导入</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="266"/>
+ <location filename="../../src/ui/Wizard.cpp" line="276"/>
<source>Imported Configuration from old GPGFrontend.&lt;br&gt;Will now restart to activate the configuration.</source>
- <translation type="unfinished"></translation>
+ <translation>从旧GPGFrontend导入配置。&lt;br&gt;现在将重新启动以激活配置。</translation>
</message>
</context>
<context>
<name>InfoBoardWidget</name>
<message>
- <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/>
<source>Import missing key from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>从密钥服务器导入丢失的密钥</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/>
+ <source>Optional Actions Menu</source>
+ <translation>可选操作菜单</translation>
</message>
</context>
<context>
<name>InfoTab</name>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="55"/>
- <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, &lt;br&gt;cross-platform, and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/>
+ <source>&lt;br&gt;&lt;center&gt;GPGFrontend is an easy-to-use, compact, cross-platform, &lt;br&gt;and installation-free gpg front-end tool.&lt;br&gt;It visualizes most of the common operations of gpg commands.&lt;br&gt;It&apos;s licensed under the GPL v3&lt;br&gt;&lt;br&gt;&lt;b&gt;Developer:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;If you have any questions or suggestions, raise an issue&lt;br/&gt;at &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; or send a mail to my mailing list at &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</source>
+ <translation>&lt;br&gt;&lt;center&gt;GPGFrontend是一个易于使用,紧凑,跨平台,无需安装的GPG前端工具。&lt;br&gt;它可视化GPG命令的大多数常见操作。&lt;br&gt;它使用GPL V3许可证&lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; 作者:&lt;/b&gt;&lt;br&gt;Saturneric&lt;br&gt;&lt;br&gt;如果你有任何疑问, 请发起一个issue&lt;br/&gt;到 &lt;a href=&quot;https://github.com/saturneric/GpgFrontend&quot;&gt;GitHub&lt;/a&gt; 或者给我发邮件 &lt;a href=&quot;mailto:[email protected]&quot;&gt;[email protected]&lt;/a&gt;.</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="63"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/>
<source>&lt;br&gt;&lt;br&gt; Built with Qt </source>
- <translation type="unfinished"></translation>
+ <translation>&lt;br&gt; &lt;br&gt;构建该程序使用了Qt</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="64"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/>
<source> and GPGME </source>
- <translation type="unfinished"></translation>
+ <translation>和gpgme</translation>
</message>
<message>
- <location filename="../../src/ui/AboutDialog.cpp" line="65"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/>
<source>&lt;br&gt;Built at </source>
- <translation type="unfinished"></translation>
+ <translation>&lt;br&gt;构建于</translation>
</message>
</context>
<context>
<name>IntroPage</name>
<message>
<location filename="../../src/ui/Wizard.cpp" line="111"/>
- <source>Getting started...</source>
- <translation type="unfinished"></translation>
+ <source>Getting Started...</source>
+ <translation>入门...</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="112"/>
<source>... with GPGFrontend</source>
- <translation type="unfinished"></translation>
+ <translation>...与GPGFrontend.</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="114"/>
- <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.&lt;br&gt;&lt;br&gt;For more information have a look at the &lt;a href=&apos;docu_concepts.html&apos;&gt;concepts&lt;/a&gt; (by clicking the link, the page will open in the main window). &lt;br&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source>
+ <translation>欢迎使用GPGFrontend进行解密和签名文本或文件!</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="116"/>
+ <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source>
+ <translation>是一个功能强大,易于使用,小巧,跨平台和无需安装的OpenPGP加密工具。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="117"/>
+ <source>For brief information have a look at the</source>
+ <translation>了解简要信息请查看</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="123"/>
+ <location filename="../../src/ui/Wizard.cpp" line="118"/>
+ <source>Overview</source>
+ <translation>概述</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="119"/>
+ <source>by clicking the link, the page will open in the web browser</source>
+ <translation>通过单击链接,页面将在Web浏览器中打开</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/Wizard.cpp" line="127"/>
<source>Choose a Language</source>
- <translation type="unfinished"></translation>
+ <translation>选择一种语言</translation>
</message>
</context>
<context>
@@ -614,22 +637,22 @@
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="31"/>
<source>KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>密钥对</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="32"/>
<source>UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="33"/>
<source>Subkeys</source>
- <translation type="unfinished"></translation>
+ <translation>子密钥</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="40"/>
<source>Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>密钥详情</translation>
</message>
</context>
<context>
@@ -637,150 +660,159 @@
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="32"/>
<source>Generate Key</source>
- <translation type="unfinished"></translation>
+ <translation>生成密钥</translation>
</message>
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="68"/>
<source> Name must contain at least five characters.
</source>
- <translation type="unfinished"></translation>
+ <translation>名称必须包含至少五个字符。</translation>
</message>
<message>
<location filename="../../src/ui/keygen/KeygenDialog.cpp" line="70"/>
<source> Please give a email address.
</source>
- <translation type="unfinished"></translation>
+ <translation>请提供电子邮件地址。</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/>
- <source> Expiration time no more than 2 years. </source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/>
+ <source> Expiration time no more than 2 years.
+</source>
+ <translation>到期时间不超过2年。</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/>
<source>Generating Key...</source>
- <translation type="unfinished"></translation>
+ <translation>生成密钥......</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/>
<source>Collecting random data for key generation.
This may take a while.
To speed up the process use your computer
(e.g. browse the net, listen to music,...)</source>
- <translation type="unfinished"></translation>
+ <translation>收集密钥生成的随机数据。
+ 可能还要等一下。
+ 加快过程使用您的计算机
+ (例如,浏览网,听音乐,......)</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/>
+ <source>Key Usage</source>
+ <translation>密钥用法</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/>
<source>Encryption</source>
- <translation type="unfinished"></translation>
+ <translation>加密</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/>
<source>Signing</source>
- <translation type="unfinished"></translation>
+ <translation>签名</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/>
<source>Certification</source>
- <translation type="unfinished"></translation>
+ <translation>认证</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/>
<source>Authentication</source>
- <translation type="unfinished"></translation>
+ <translation>验证</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>Success</source>
- <translation type="unfinished"></translation>
+ <translation>成功</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/>
<source>The new key pair has been generated.</source>
- <translation type="unfinished"></translation>
+ <translation>已生成新的密钥对。</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>Failure</source>
- <translation type="unfinished"></translation>
+ <translation>失败</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/>
<source>An error occurred during key generation.</source>
- <translation type="unfinished"></translation>
+ <translation>密钥生成期间发生错误。</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/>
<source>Name:</source>
- <translation type="unfinished"></translation>
+ <translation>名称:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/>
<source>Email Address:</source>
- <translation type="unfinished"></translation>
+ <translation>电子邮件地址:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/>
<source>Comment:</source>
- <translation type="unfinished"></translation>
+ <translation>备注:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/>
<source>Expiration Date:</source>
- <translation type="unfinished"></translation>
+ <translation>过期日期:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>永不过期</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/>
<source>KeySize (in Bit):</source>
- <translation type="unfinished"></translation>
+ <translation>密钥长度(位):</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/>
<source>Key Type:</source>
- <translation type="unfinished"></translation>
+ <translation>密钥类型:</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/>
<source>Non Pass Phrase</source>
- <translation type="unfinished"></translation>
+ <translation>无需密码保护</translation>
</message>
<message>
- <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/>
+ <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/>
<source>Basic Information</source>
- <translation type="unfinished"></translation>
+ <translation>基本信息</translation>
</message>
</context>
<context>
<name>KeyGenPage</name>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="356"/>
+ <location filename="../../src/ui/Wizard.cpp" line="366"/>
<source>Create a keypair...</source>
- <translation type="unfinished"></translation>
+ <translation>新建一个密钥对......</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="357"/>
+ <location filename="../../src/ui/Wizard.cpp" line="367"/>
<source>...for decrypting and signing messages</source>
- <translation type="unfinished"></translation>
+ <translation>...用于解密和签名消息</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="358"/>
+ <location filename="../../src/ui/Wizard.cpp" line="368"/>
<source>You should create a new keypair.The pair consists of a public and a private key.&lt;br&gt;Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.&lt;br&gt;For more information have a look at the offline tutorial (which then is shown in the main window):</source>
- <translation type="unfinished"></translation>
+ <translation>您应该创建一个新的keypair.该金对由公共和私钥组成。&lt;br&gt;其他用户可以使用公钥来加密为您的消息,并验证由您签名的消息。您可以使用私钥来解密和签名消息。&lt;br&gt; &lt;br&gt;更多信息看看脱机教程(然后在主窗口中显示):</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="365"/>
+ <location filename="../../src/ui/Wizard.cpp" line="375"/>
<source>Offline tutorial</source>
- <translation type="unfinished"></translation>
+ <translation>离线教程</translation>
</message>
<message>
- <location filename="../../src/ui/Wizard.cpp" line="372"/>
+ <location filename="../../src/ui/Wizard.cpp" line="382"/>
<source>Create New Key</source>
- <translation type="unfinished"></translation>
+ <translation>创建新密钥</translation>
</message>
</context>
<context>
@@ -789,118 +821,118 @@
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="53"/>
<source>Key Update Details</source>
- <translation type="unfinished"></translation>
+ <translation>密钥更新详细信息</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/>
<source>No keys found</source>
- <translation type="unfinished"></translation>
+ <translation>没有找到密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="55"/>
<source>Key Import Details</source>
- <translation type="unfinished"></translation>
+ <translation>密钥导入详细信息</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/>
<source>No keys found to import</source>
- <translation type="unfinished"></translation>
+ <translation>没有发现导入的密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="64"/>
<source>General key info</source>
- <translation type="unfinished"></translation>
+ <translation>通用密钥信息</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="67"/>
<source>Considered:</source>
- <translation type="unfinished"></translation>
+ <translation>经过考虑的:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="71"/>
<source>Public unchanged:</source>
- <translation type="unfinished"></translation>
+ <translation>公开未改变的:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="76"/>
<source>Imported:</source>
- <translation type="unfinished"></translation>
+ <translation>导入:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="81"/>
<source>Not imported:</source>
- <translation type="unfinished"></translation>
+ <translation>未导入:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="86"/>
<source>Private read:</source>
- <translation type="unfinished"></translation>
+ <translation>私有读取:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="91"/>
<source>Private imported:</source>
- <translation type="unfinished"></translation>
+ <translation>私有导入:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="96"/>
<source>Private unchanged:</source>
- <translation type="unfinished"></translation>
+ <translation>私有未改变的:</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>名称</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>电子邮件</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Status</source>
- <translation type="unfinished"></translation>
+ <translation>状态</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/>
<source>Fingerprint</source>
- <translation type="unfinished"></translation>
+ <translation>指纹</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="135"/>
<source>private</source>
- <translation type="unfinished"></translation>
+ <translation>私有的</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="138"/>
<source>public</source>
- <translation type="unfinished"></translation>
+ <translation>公有</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="141"/>
<source>unchanged</source>
- <translation type="unfinished"></translation>
+ <translation>不变的</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="144"/>
<source>new key</source>
- <translation type="unfinished"></translation>
+ <translation>新密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="147"/>
<source>new subkey</source>
- <translation type="unfinished"></translation>
+ <translation>新子密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="151"/>
<source>new signature</source>
- <translation type="unfinished"></translation>
+ <translation>新签名</translation>
</message>
<message>
<location filename="../../src/ui/KeyImportDetailDialog.cpp" line="155"/>
<source>new uid</source>
- <translation type="unfinished"></translation>
+ <translation>新UID</translation>
</message>
</context>
<context>
@@ -908,309 +940,310 @@
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Select</source>
- <translation type="unfinished"></translation>
+ <translation>选择</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Type</source>
- <translation type="unfinished"></translation>
+ <translation>类型</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>名称</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="77"/>
<source>Email Address</source>
- <translation type="unfinished"></translation>
+ <translation>电子邮件地址</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Usage</source>
- <translation type="unfinished"></translation>
+ <translation>用法</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Validity</source>
- <translation type="unfinished"></translation>
+ <translation>有效性</translation>
</message>
<message>
<location filename="../../src/ui/widgets/KeyList.cpp" line="78"/>
<source>Finger Print</source>
- <translation type="unfinished"></translation>
+ <translation>指纹</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
<source>Import Keys</source>
- <translation type="unfinished"></translation>
+ <translation>导入密钥</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/>
<source>You&apos;ve dropped something on the table.
GpgFrontend will now try to import key(s).</source>
- <translation type="unfinished"></translation>
+ <translation>你拖拽了某些文件到表格上。
+ GPGFrontend现在将尝试导入密钥。</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/>
<source>Always import without bothering.</source>
- <translation type="unfinished"></translation>
+ <translation>始终导入而不再询问。</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/>
+ <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/>
<source>Couldn&apos;t Open File: </source>
- <translation type="unfinished"></translation>
+ <translation>无法打开文件:</translation>
</message>
</context>
<context>
<name>KeyMgmt</name>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="81"/>
- <source>KeyPairs Management</source>
- <translation type="unfinished"></translation>
+ <source>Key Pair Management</source>
+ <translation>密钥对管理</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="88"/>
<source>&amp;Open</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;打开</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="89"/>
<source>Ctrl+O</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + O.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="90"/>
<source>Open Key File</source>
- <translation type="unfinished"></translation>
+ <translation>打开密钥文件</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="93"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;关闭</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="94"/>
<source>Ctrl+Q</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + Q.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="96"/>
<source>Close</source>
- <translation type="unfinished"></translation>
+ <translation>关闭</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="99"/>
<source>New Keypair</source>
- <translation type="unfinished"></translation>
+ <translation>新密钥对</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="100"/>
<source>Ctrl+N</source>
- <translation type="unfinished"></translation>
+ <translation>Ctrl + N.</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="102"/>
<source>Generate KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>生成密钥对</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="105"/>
<source>New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>新子密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="106"/>
<source>Ctrl+Shift+N</source>
- <translation type="unfinished"></translation>
+ <translation>ctrl + shift + n</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="108"/>
<source>Generate Subkey For Selected KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>为选定的keypair生成subkey</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="111"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="152"/>
<source>&amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;文件</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="113"/>
<source>Import New Key From File</source>
- <translation type="unfinished"></translation>
+ <translation>从文件导入新密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="116"/>
<source>&amp;Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;剪贴板</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="118"/>
<source>Import New Key From Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>从剪贴板导入新密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="121"/>
<source>&amp;Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;密钥服务器</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="123"/>
<source>Import New Key From Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>从密钥服务器导入新密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="126"/>
<source>Export To &amp;Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>导出到剪贴板</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="128"/>
<source>Export Selected Key(s) To Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>将所选密钥导出到剪贴板</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="131"/>
<source>Export To &amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>导出到&amp;文件</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="133"/>
<source>Export Selected Key(s) To File</source>
- <translation type="unfinished"></translation>
+ <translation>将所选密钥导出到文件</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="136"/>
<source>Delete Selected Key(s)</source>
- <translation type="unfinished"></translation>
+ <translation>删除所选密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="137"/>
<source>Delete the Selected keys</source>
- <translation type="unfinished"></translation>
+ <translation>删除所选密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="140"/>
<source>Delete Checked Key(s)</source>
- <translation type="unfinished"></translation>
+ <translation>删除已选密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="141"/>
<source>Delete the Checked keys</source>
- <translation type="unfinished"></translation>
+ <translation>删除已选中的密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="145"/>
<source>Show Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>显示密钥详情</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="146"/>
<source>Show Details for this Key</source>
- <translation type="unfinished"></translation>
+ <translation>显示此密钥的详细信息</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="156"/>
<source>&amp;Key</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="157"/>
<source>&amp;Generate Key</source>
- <translation type="unfinished"></translation>
+ <translation>生成密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="161"/>
<source>&amp;Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;导入密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="173"/>
<source>Key</source>
- <translation type="unfinished"></translation>
+ <translation>密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="181"/>
<source>Generate</source>
- <translation type="unfinished"></translation>
+ <translation>生成</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="182"/>
<source>Generate A New Keypair or Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>生成一个新的keypair或subkey</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="191"/>
<source>Import key</source>
- <translation type="unfinished"></translation>
+ <translation>导入密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="192"/>
<source>Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>导入密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<source>Open Key</source>
- <translation type="unfinished"></translation>
+ <translation>打开密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="299"/>
<source>Key Files</source>
- <translation type="unfinished"></translation>
+ <translation>密钥文件</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="213"/>
<source>Keyring files</source>
- <translation type="unfinished"></translation>
+ <translation>密钥入文件</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="218"/>
<source>Couldn&apos;t Open File: </source>
- <translation type="unfinished"></translation>
+ <translation>无法打开文件:</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="268"/>
<source>Deleting Keys</source>
- <translation type="unfinished"></translation>
+ <translation>删除密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="269"/>
<source>Are you sure that you want to delete the following keys?</source>
- <translation type="unfinished"></translation>
+ <translation>您确定要删除以下密钥吗?</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="270"/>
<source>The action can not be undone.</source>
- <translation type="unfinished"></translation>
+ <translation>行动无法撤消。</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="299"/>
<source>Export Key To File</source>
- <translation type="unfinished"></translation>
+ <translation>导出文件</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="309"/>
<source>key(s) exported</source>
- <translation type="unfinished"></translation>
+ <translation>密钥导出</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="338"/>
<location filename="../../src/ui/KeyMgmt.cpp" line="345"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>操作无效</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="339"/>
<source>Please select one KeyPair before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>请在执行此操作之前选择一个keypair。</translation>
</message>
<message>
<location filename="../../src/ui/KeyMgmt.cpp" line="346"/>
<source>If a key pair does not have a private key then it will not be able to generate sub-keys.</source>
- <translation type="unfinished"></translation>
+ <translation>如果密钥对没有私钥,则它将无法生成子密钥。</translation>
</message>
</context>
<context>
@@ -1218,198 +1251,247 @@
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="40"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>名称</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="41"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>电子邮件</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="42"/>
<source>Comment</source>
- <translation type="unfinished"></translation>
+ <translation>备注</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="55"/>
<source>Create New UID</source>
- <translation type="unfinished"></translation>
+ <translation>创建新UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="68"/>
<source> Name must contain at least five characters.
</source>
- <translation type="unfinished"></translation>
+ <translation>名称必须包含至少五个字符。</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="70"/>
<source> Please give a email address.
</source>
- <translation type="unfinished"></translation>
+ <translation>请提供电子邮件地址。</translation>
</message>
</context>
<context>
<name>KeyPairDetailTab</name>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
<source>Owner</source>
- <translation type="unfinished"></translation>
+ <translation>所有者</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
<source>Master Key</source>
- <translation type="unfinished"></translation>
+ <translation>主密钥</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/>
<source>Fingerprint</source>
- <translation type="unfinished"></translation>
+ <translation>指纹</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/>
<source>Additional UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>额外的UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Exists</source>
+ <translation>存在</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/>
+ <source>Not Exists</source>
+ <translation>不存在</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
<source>Name:</source>
- <translation type="unfinished"></translation>
+ <translation>名称:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/>
<source>Email Address:</source>
- <translation type="unfinished"></translation>
+ <translation>电子邮件地址:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/>
<source>Comment:</source>
- <translation type="unfinished"></translation>
+ <translation>备注:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
<source>Key ID: </source>
- <translation type="unfinished"></translation>
+ <translation>密钥ID:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
<source>Algorithm: </source>
- <translation type="unfinished"></translation>
+ <translation>算法:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
<source>Key Size:</source>
- <translation type="unfinished"></translation>
+ <translation>密钥长度:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
<source>Nominal Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>名义用法:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
<source>Actual Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>实际用法:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
<source>Expires on: </source>
- <translation type="unfinished"></translation>
+ <translation>到期:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/>
<source>Last Update: </source>
- <translation type="unfinished"></translation>
+ <translation>最后更新:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/>
<source>Secret Key Existence: </source>
- <translation type="unfinished"></translation>
+ <translation>主密钥存在:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
<source>Copy</source>
- <translation type="unfinished"></translation>
+ <translation>复制</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/>
<source>copy fingerprint to clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>将指纹复制到剪贴板</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/>
<source>Operations</source>
- <translation type="unfinished"></translation>
+ <translation>操作</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/>
+ <source>Export Private Key (Include Subkey)</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/>
+ <source>You are about to export your</source>
+ <translation>你现在正在导出</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/>
+ <source>PRIVATE KEY</source>
+ <translation>私钥</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/>
+ <source>This is NOT your Public Key, so DON&apos;T give it away.</source>
+ <translation>这不是公钥,所以不要随意放置</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/>
+ <source>Do you REALLY want to export your PRIVATE KEY?</source>
+ <translation>你真的想要导出该私钥吗</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/>
<source>Export Private Key (Include Subkeys)</source>
- <translation type="unfinished"></translation>
+ <translation type="obsolete">导出私钥(包括子密钥)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/>
<source>Modify Expiration Datetime (Master Key)</source>
- <translation type="unfinished"></translation>
+ <translation>修改到期日期时间(主密钥)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/>
<source>Key Server Operation (Pubkey)</source>
- <translation type="unfinished"></translation>
+ <translation>密钥服务器操作(Pubkey)</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/>
+ <source>Generate Revoke Certificate</source>
+ <translation>生成撤销证书</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/>
<source>Warning: The Master Key has expired.</source>
- <translation type="unfinished"></translation>
+ <translation>警告:主密钥已过期。</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/>
<source>Warning: The Master Key has been revoked</source>
- <translation type="unfinished"></translation>
+ <translation>警告:主密钥已被撤销</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/>
<source>Exporting private Key</source>
- <translation type="unfinished"></translation>
+ <translation>导出私钥</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/>
<source>&lt;h3&gt;You are about to export your &lt;font color=&quot;red&quot;&gt;PRIVATE KEY&lt;/font&gt;!&lt;/h3&gt;
This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALLY want to export your PRIVATE KEY?</source>
- <translation type="unfinished"></translation>
+ <translation type="vanished">&lt;h3&gt;您即将导出&lt;font color =“红色”&gt;私钥&lt;/ font&gt;!&lt;/ h3&gt;
+这不是你的公钥,所以随意放置它。&lt;br /&gt;你真的想导出私钥吗?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/>
<source>Export Key To File</source>
- <translation type="unfinished"></translation>
+ <translation>导出文件</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/>
<source>Key Files</source>
- <translation type="unfinished"></translation>
+ <translation>密钥文件</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Export Error</source>
- <translation type="unfinished"></translation>
+ <translation>导出错误</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/>
<source>Couldn&apos;t open %1 for writing</source>
- <translation type="unfinished"></translation>
+ <translation>无法打开%1来写作</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>永不过期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/>
- <source>Upload Key Pair</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/>
+ <source>Upload Key Pair to Key Server</source>
+ <translation>将密钥对上传到密钥服务器</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/>
<source>Update Key Pair</source>
- <translation type="unfinished"></translation>
+ <translation>更新密钥对</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/>
+ <source>Generate revocation certificate</source>
+ <translation>生成撤销证书</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/>
+ <source>Revocation Certificates</source>
+ <translation>撤销证书</translation>
</message>
</context>
<context>
@@ -1417,87 +1499,87 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="37"/>
<source>Generate A New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>生成一个新的子密钥</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
<source>Key ID: </source>
- <translation type="unfinished"></translation>
+ <translation>密钥ID:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
<source>Algorithm: </source>
- <translation type="unfinished"></translation>
+ <translation>算法:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
<source>Key Size:</source>
- <translation type="unfinished"></translation>
+ <translation>密钥大小:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
<source>Usage: </source>
- <translation type="unfinished"></translation>
+ <translation>用法:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
<source>Expires On </source>
- <translation type="unfinished"></translation>
+ <translation>到期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
<source>Last Update: </source>
- <translation type="unfinished"></translation>
+ <translation>最后更新:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
<source>Existence: </source>
- <translation type="unfinished"></translation>
+ <translation>存在:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/>
<source>Fingerprint: </source>
- <translation type="unfinished"></translation>
+ <translation>指纹:</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Subkey ID</source>
- <translation type="unfinished"></translation>
+ <translation>次要ID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Key Size</source>
- <translation type="unfinished"></translation>
+ <translation>密钥大小</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Algo</source>
- <translation type="unfinished"></translation>
+ <translation>某物</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Create Date</source>
- <translation type="unfinished"></translation>
+ <translation>创建日期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/>
<source>Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>到期日期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>永不过期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/>
<source>Never Expires</source>
- <translation type="unfinished"></translation>
+ <translation>永远不会到期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/>
+ <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/>
<source>Edit Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>编辑到期日期</translation>
</message>
</context>
<context>
@@ -1505,192 +1587,202 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="39"/>
<source>New UID</source>
- <translation type="unfinished"></translation>
+ <translation>新UID</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="40"/>
<source>UID Management</source>
- <translation type="unfinished"></translation>
+ <translation>UID管理</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/>
+ <source>UIDs</source>
+ <translation>UID</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/>
+ <source>Signature of Selected UID</source>
+ <translation>已选择UID包含的签名</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Select</source>
- <translation type="unfinished"></translation>
+ <translation>选择</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Name</source>
- <translation type="unfinished"></translation>
+ <translation>名称</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Email</source>
- <translation type="unfinished"></translation>
+ <translation>电子邮件</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/>
<source>Comment</source>
- <translation type="unfinished"></translation>
+ <translation>备注</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Key ID</source>
- <translation type="unfinished"></translation>
+ <translation>密钥ID.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Create Date</source>
- <translation type="unfinished"></translation>
+ <translation>创建日期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/>
<source>Expired Date</source>
- <translation type="unfinished"></translation>
+ <translation>过期日期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/>
<source>Never Expires</source>
- <translation type="unfinished"></translation>
+ <translation>永远不会到期</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>操作无效</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/>
<source>Please select one or more UIDs before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>请在执行此操作之前选择一个或多个UID。</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/>
<source>Sign Selected UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>签名所选UID(s)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/>
<source>Delete Selected UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>删除所选的UID(s)</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/>
<source>Successful Operation</source>
- <translation type="unfinished"></translation>
+ <translation>成功运作</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
<source>Successfully added a new UID.</source>
- <translation type="unfinished"></translation>
+ <translation>成功添加了一个新的UID。</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/>
<source>Operation Failed</source>
- <translation type="unfinished"></translation>
+ <translation>操作失败</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/>
<source>An error occurred during the operation.</source>
- <translation type="unfinished"></translation>
+ <translation>操作期间发生错误。</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/>
<source>Deleting UIDs</source>
- <translation type="unfinished"></translation>
+ <translation>删除UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/>
<source>Are you sure that you want to delete the following uids?</source>
- <translation type="unfinished"></translation>
+ <translation>您确定要删除以下UID吗?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/>
<source>The action can not be undone.</source>
- <translation type="unfinished"></translation>
+ <translation>行动无法撤消。</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/>
<source>Set Primary UID</source>
- <translation type="unfinished"></translation>
+ <translation>设置主UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/>
<source>Are you sure that you want to set the Primary UID to?</source>
- <translation type="unfinished"></translation>
+ <translation>您确定要将主UID设置为吗?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/>
<source>Set As Primary</source>
- <translation type="unfinished"></translation>
+ <translation>设为主要</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/>
<source>Sign UID</source>
- <translation type="unfinished"></translation>
+ <translation>签名UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/>
<source>Delete UID</source>
- <translation type="unfinished"></translation>
+ <translation>删除UID.</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/>
<source>Please select one UID before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>在执行此操作之前,请选择一个UID。</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/>
<source>Deleting UID</source>
- <translation type="unfinished"></translation>
+ <translation>删除UID</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/>
<source>Are you sure that you want to delete the following uid?</source>
- <translation type="unfinished"></translation>
+ <translation>您确定要删除以下UID吗?</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/>
<source>Delete(Revoke) Key Signature</source>
- <translation type="unfinished"></translation>
+ <translation>删除(撤消)密钥签名</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/>
<source>Please select one Key Signature before doing this operation.</source>
- <translation type="unfinished"></translation>
+ <translation>请在执行此操作之前选择一个密钥签名。</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/>
<source>To delete the signature, you need to have its corresponding public key in the local database.</source>
- <translation type="unfinished"></translation>
+ <translation>要删除签名,您需要在本地数据库中拥有其相应的公钥。</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/>
<source>Deleting Key Signature</source>
- <translation type="unfinished"></translation>
+ <translation>删除密钥签名</translation>
</message>
<message>
- <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/>
+ <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/>
<source>Are you sure that you want to delete the following signature?</source>
- <translation type="unfinished"></translation>
+ <translation>您确定要删除以下签名吗?</translation>
</message>
</context>
<context>
@@ -1698,140 +1790,140 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="40"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;关闭</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="41"/>
<source>&amp;Import ALL</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;导入全部</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="42"/>
<source>&amp;Search</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;搜索</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="45"/>
<source>Search String:</source>
- <translation type="unfinished"></translation>
+ <translation>搜索字符串:</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="49"/>
<source>Key Server:</source>
- <translation type="unfinished"></translation>
+ <translation>密钥服务器:</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="97"/>
<source>Update Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>从密钥服务器更新密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="99"/>
<source>Import Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>从密钥服务器导入密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>UID</source>
- <translation type="unfinished"></translation>
+ <translation>uid</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>Creation date</source>
- <translation type="unfinished"></translation>
+ <translation>创建日期</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>KeyID</source>
- <translation type="unfinished"></translation>
+ <translation>keyid.</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/>
<source>Tag</source>
- <translation type="unfinished"></translation>
+ <translation>标签</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/>
- <source>&lt;h4&gt;Text is empty.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <source>Text is empty.</source>
+ <translation>文本为空</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/>
+ <source>Too many responses from keyserver!</source>
+ <translation>太多来自密钥服务器的响应</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/>
+ <source>No keys found, input may be kexId, retrying search with 0x.</source>
+ <translation>没有找到密钥,尝试使用密钥标识搜索。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/>
+ <source>No keys found containing the search string!</source>
+ <translation>没有发现包含搜索字符串的密钥!</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/>
+ <source>Insufficiently specific search string!</source>
+ <translation>特定的搜索字符串不足!</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/>
<source>Not Key Found</source>
- <translation type="unfinished"></translation>
+ <translation>没有密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/>
<source>Timeout</source>
- <translation type="unfinished"></translation>
+ <translation>超时</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/>
<source>Key Server Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>找不到密钥服务器</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/>
<source>Connection Error</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/>
- <source>&lt;h4&gt;CToo many responses from keyserver!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/>
- <source>&lt;h4&gt;No keys found, input may be kexId, retrying search with 0x.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/>
- <source>&lt;h4&gt;No keys found containing the search string!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/>
- <source>&lt;h4&gt;Insufficiently specific search string!&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>连接错误</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="274"/>
<source>revoked</source>
- <translation type="unfinished"></translation>
+ <translation>撤销</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="277"/>
<source>disabled</source>
- <translation type="unfinished"></translation>
+ <translation>禁用</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="317"/>
<source>&lt;h4&gt;%1 keys found. Double click a key to import it.&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>找到&lt;h4&gt;%1密钥。双击将密钥导入它。&lt;/ h4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="383"/>
<source>Key Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>找不到密钥</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="410"/>
<source>&lt;h4&gt;Key Updated&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;h4&gt;密钥更新&lt;/ h4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="412"/>
<source>&lt;h4&gt;Key Imported&lt;/h4&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;H4&gt;密钥导入&lt;/ h4&gt;</translation>
</message>
<message>
<location filename="../../src/ui/KeyServerImportDialog.cpp" line="473"/>
<source>Upload Keys from Keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>从密钥服务器上传密钥</translation>
</message>
</context>
<context>
@@ -1839,22 +1931,22 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="36"/>
<source>Confirm</source>
- <translation type="unfinished"></translation>
+ <translation>确认</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="41"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>永不过期</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="61"/>
<source>Operation Failed</source>
- <translation type="unfinished"></translation>
+ <translation>操作失败</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="62"/>
<source>An error occurred during the operation.</source>
- <translation type="unfinished"></translation>
+ <translation>操作期间发生错误。</translation>
</message>
</context>
<context>
@@ -1862,801 +1954,856 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="72"/>
<source>Expire Date</source>
- <translation type="unfinished"></translation>
+ <translation>到期日期</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="81"/>
<source>Sign For Key&apos;s UID(s)</source>
- <translation type="unfinished"></translation>
+ <translation>为密钥的UID签名</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="100"/>
<source>Unsuccessful Operation</source>
- <translation type="unfinished"></translation>
+ <translation>不成功的操作</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="101"/>
<source>Signature operation failed for UID </source>
- <translation type="unfinished"></translation>
+ <translation>UID的签名操作失败</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="108"/>
<source>Operation Complete</source>
- <translation type="unfinished"></translation>
+ <translation>操作完成</translation>
</message>
<message>
<location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="109"/>
<source>The signature operation of the UID is complete</source>
- <translation type="unfinished"></translation>
+ <translation>UID的签名操作是完整的</translation>
</message>
</context>
<context>
<name>KeyUploadDialog</name>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/>
<source>Uploading Public Key</source>
- <translation type="unfinished"></translation>
+ <translation>上传公钥</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/>
<source>Key Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>找不到密钥</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/>
<source>Timeout</source>
- <translation type="unfinished"></translation>
+ <translation>超时</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/>
<source>Key Server Not Found</source>
- <translation type="unfinished"></translation>
+ <translation>找不到密钥服务器</translation>
</message>
<message>
- <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/>
+ <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/>
<source>Connection Error</source>
- <translation type="unfinished"></translation>
+ <translation>连接错误</translation>
</message>
</context>
<context>
<name>KeyserverTab</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="508"/>
- <source>Default Keyserver for import:</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="607"/>
+ <source>Default Key Server for import:</source>
+ <translation>导入的默认密钥服务器:</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="525"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="624"/>
<source>Add</source>
- <translation type="unfinished"></translation>
+ <translation>添加</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/>
+ <location filename="../../src/MainWindow.cpp" line="35"/>
+ <source>Loading Gnupg</source>
+ <translation>正在加载Gnupg</translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="62"/>
+ <source>ENV Loading Failed</source>
+ <translation>ENV Loading失败了</translation>
+ </message>
+ <message>
+ <location filename="../../src/MainWindow.cpp" line="63"/>
+ <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source>
+ <translation>GNUPG未正确安装,请按照README说明安装GNUPG,然后打开GPGFrontend。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/>
<source>No Key Selected</source>
- <translation type="unfinished"></translation>
+ <translation>没有选择密钥</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/>
<source>Invalid Operation</source>
- <translation type="unfinished"></translation>
+ <translation>操作无效</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/>
<source>The selected key contains a key that does not actually have a encrypt usage.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>所选密钥包含一个实际上没有加密使用的密钥。&lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/>
+ <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
+ <translation>&lt;br/&gt;例如以下密钥:&lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/>
+ <source>Encrypting</source>
+ <translation>加密</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/>
+ <source>Function Disabled</source>
+ <translation>功能已禁用</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/>
+ <source>Please go to the settings interface to enable and configure this function.</source>
+ <translation>请转到“设置”界面以启用和配置此功能。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/>
<source>The selected key contains a key that does not actually have a signature usage.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>所选密钥包含一个实际上没有签名使用的密钥。&lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/>
+ <source>Signing</source>
+ <translation>签名</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/>
+ <source>Decrypting</source>
+ <translation>解密</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/>
+ <source>Verifying</source>
+ <translation>验证</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/>
<source>Invalid KeyPair</source>
- <translation type="unfinished"></translation>
+ <translation>无效的密钥对</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/>
<source>The selected keypair cannot be used for signing and encryption at the same time.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>选定的密钥对不能同时使用用于签名和加密。&lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/>
<source>Incomplete Operation</source>
- <translation type="unfinished"></translation>
+ <translation>不完整的操作</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/>
<source>None of the selected key pairs can provide the encryption function.</source>
- <translation type="unfinished"></translation>
+ <translation>没有选定的密钥对可以提供加密功能。</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/>
<source>None of the selected key pairs can provide the signature function.</source>
- <translation type="unfinished"></translation>
+ <translation>没有选定的密钥对可以提供签名功能。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/>
+ <source>Encrypting and Signing</source>
+ <translation>加密和签名</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/>
+ <source>Decrypting and Verifying</source>
+ <translation>解密和验证</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
<location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>Error</source>
- <translation type="unfinished"></translation>
+ <translation>错误</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/>
+ <source>Select a file before doing it.</source>
+ <translation>在执行此操作之前选择文件。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/>
<source>No permission to read this file.</source>
- <translation type="unfinished"></translation>
+ <translation>无权限读取此文件。</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/>
<source>No permission to create file.</source>
- <translation type="unfinished"></translation>
+ <translation>无权限创建文件。</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>警告</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/>
<source>The target file already exists, do you need to overwrite it?</source>
- <translation type="unfinished"></translation>
+ <translation>目标文件已存在,您是否需要覆盖它?</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/>
<source>An error occurred during operation.</source>
- <translation type="unfinished"></translation>
+ <translation>操作期间发生错误。</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/>
<source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source>
- <translation type="unfinished"></translation>
+ <translation>请选择相应的目标文件或签名文件。确保两者都在此目录中。</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/>
<source>No permission to read target file.</source>
- <translation type="unfinished"></translation>
+ <translation>无权限读取目标文件。</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/>
<source>No permission to read signature file.</source>
- <translation type="unfinished"></translation>
+ <translation>无权限读取签名文件。</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/>
<source>Select a file(.gpg/.asc) before doing it.</source>
- <translation type="unfinished"></translation>
+ <translation>在做之前选择一个文件(.gpg / .casc)。</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/>
- <source>&lt;br/&gt;For example the Following Key: &lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/>
+ <source>Outdated Version</source>
+ <translation>过时的版本</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/>
- <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/>
- <source>Select a file before doing it.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/>
+ <source>This version(%1) is out of date, please update the latest version in time. </source>
+ <translation>此版本(%1)已过期,请及时更新最新版本。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/>
+ <source>You can download the latest version(%1) on Github Releases Page.&lt;br/&gt;</source>
+ <translation>您可以在Github发布页面上下载最新版本(%1)。&lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/>
+ <source>Unreleased Version</source>
+ <translation>未发布的版本</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/>
+ <source>This version(%1) has not been officially released and is not recommended for use in a production environment. &lt;br/&gt;</source>
+ <translation>此版本(%1)尚未正式发布,不建议在生产环境中使用。&lt;BR/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/>
<source>There is one unencrypted file in attachment folder</source>
- <translation type="unfinished"></translation>
+ <translation>附件文件夹中有一个未加密的文件</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source>There are </source>
- <translation type="unfinished"></translation>
+ <translation>有</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/>
+ <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/>
<source> unencrypted files in attachment folder</source>
- <translation type="unfinished"></translation>
+ <translation>附件文件夹中的未加密文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="30"/>
<source>&amp;New</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;新标签页</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="36"/>
<source>Open a new file</source>
- <translation type="unfinished"></translation>
+ <translation>打开一个新文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="39"/>
<source>&amp;Open...</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;打开...</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="42"/>
<source>Open an existing file</source>
- <translation type="unfinished"></translation>
+ <translation>打开现有文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="45"/>
<source>&amp;Browser</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;文件查看器</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="47"/>
<source>Open a file browser</source>
- <translation type="unfinished"></translation>
+ <translation>打开文件浏览器</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="50"/>
<source>&amp;Save</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;保存</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="53"/>
<source>Save the current File</source>
- <translation type="unfinished"></translation>
+ <translation>保存当前文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="56"/>
<source>Save &amp;As</source>
- <translation type="unfinished"></translation>
+ <translation>另存为</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="59"/>
<source>Save the current File as...</source>
- <translation type="unfinished"></translation>
+ <translation>将当前文件保存为...</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="62"/>
<source>&amp;Print</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;打印</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="65"/>
<source>Print Document</source>
- <translation type="unfinished"></translation>
+ <translation>打印文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="68"/>
<source>&amp;Close</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;关闭标签页</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="70"/>
<source>Close file</source>
- <translation type="unfinished"></translation>
+ <translation>关闭文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="73"/>
<source>&amp;Quit</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;关闭</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="76"/>
<source>Quit Program</source>
- <translation type="unfinished"></translation>
+ <translation>退出程序</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="81"/>
<source>&amp;Undo</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;撤消</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="83"/>
<source>Undo Last Edit Action</source>
- <translation type="unfinished"></translation>
+ <translation>撤消上次编辑操作</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="86"/>
<source>&amp;Redo</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;重做</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="88"/>
<source>Redo Last Edit Action</source>
- <translation type="unfinished"></translation>
+ <translation>重做上次编辑动作</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="91"/>
<source>Zoom In</source>
- <translation type="unfinished"></translation>
+ <translation>放大</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="95"/>
<source>Zoom Out</source>
- <translation type="unfinished"></translation>
+ <translation>缩小</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="99"/>
<source>&amp;Paste</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;粘贴</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="102"/>
<source>Paste Text From Clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>从剪贴板导出文本</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="105"/>
<source>Cu&amp;t</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;剪切</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="108"/>
<source>Cut the current selection&apos;s contents to the clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>将当前选择的内容切割到剪贴板上</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="112"/>
<source>&amp;Copy</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;复制</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="115"/>
<source>Copy the current selection&apos;s contents to the clipboard</source>
- <translation type="unfinished"></translation>
+ <translation>将当前选择的内容复制到剪贴板</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="119"/>
<source>&amp;Quote</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;引用</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="121"/>
<source>Quote whole text</source>
- <translation type="unfinished"></translation>
+ <translation>引用整个文本</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="124"/>
<source>Select &amp;All</source>
- <translation type="unfinished"></translation>
+ <translation>全选</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="127"/>
<source>Select the whole text</source>
- <translation type="unfinished"></translation>
+ <translation>选择整个文本</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="130"/>
<source>&amp;Find</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;查找</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="132"/>
<source>Find a word</source>
- <translation type="unfinished"></translation>
+ <translation>查找一个单词</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="135"/>
<source>Remove &amp;spacing</source>
- <translation type="unfinished"></translation>
+ <translation>删除&amp;间距</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="138"/>
<source>Remove double linebreaks, e.g. in pasted text from webmailer</source>
- <translation type="unfinished"></translation>
+ <translation>删除双重剪辑,例如在webmailer的导出文本中</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="141"/>
<source>Se&amp;ttings</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;设置</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="142"/>
<source>Open settings dialog</source>
- <translation type="unfinished"></translation>
+ <translation>打开设置对话框</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="148"/>
<source>&amp;Encrypt</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;加密</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="151"/>
<source>Encrypt Message</source>
- <translation type="unfinished"></translation>
+ <translation>加密消息</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="154"/>
<source>&amp;Encrypt &amp;Sign</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;加密&amp;签名</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="157"/>
<source>Encrypt and Sign Message</source>
- <translation type="unfinished"></translation>
+ <translation>加密和签名消息</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="160"/>
<source>&amp;Decrypt</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;解密</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="163"/>
<source>Decrypt Message</source>
- <translation type="unfinished"></translation>
+ <translation>解密消息</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="166"/>
<source>&amp;Decrypt &amp;Verify</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;解密和验证</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="169"/>
<source>Decrypt and Verify Message</source>
- <translation type="unfinished"></translation>
+ <translation>解密和验证消息</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="175"/>
<source>&amp;Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>加密文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="176"/>
<source>Encrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>加密文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="179"/>
<source>&amp;Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>解密文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="180"/>
<source>Decrypt File</source>
- <translation type="unfinished"></translation>
+ <translation>解密文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="183"/>
<source>&amp;Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;签名文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="184"/>
<source>Sign File</source>
- <translation type="unfinished"></translation>
+ <translation>签名文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="187"/>
<source>&amp;Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;验证文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="188"/>
<source>Verify File</source>
- <translation type="unfinished"></translation>
+ <translation>验证文件</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="192"/>
<source>&amp;Sign</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;签名</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="195"/>
<source>Sign Message</source>
- <translation type="unfinished"></translation>
+ <translation>签名消息</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="198"/>
<source>&amp;Verify</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;验证</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="201"/>
<source>Verify Message</source>
- <translation type="unfinished"></translation>
+ <translation>验证消息</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="207"/>
<source>&amp;Editor</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;编辑器</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="209"/>
<source>Import New Key From Editor</source>
- <translation type="unfinished"></translation>
+ <translation>从编辑器导入新密钥</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/>
- <source>Manage &amp;keys</source>
- <translation type="unfinished"></translation>
+ <source>Manage &amp;Keys</source>
+ <translation>管理和密钥</translation>
</message>
<message>
<location filename="../../src/ui/main_window/MainWindowUI.cpp" line="214"/>
<source>Open Keymanagement</source>
- <translation type="unfinished"></translation>
+ <translation>打开密钥管理</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/>
<source>&amp;About</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;关于</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/>
<source>Show the application&apos;s About box</source>
- <translation type="unfinished"></translation>
+ <translation>显示应用程序的框</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/>
+ <source>&amp;Check for Updates</source>
+ <translation>检查更新</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <source>Check for updates</source>
+ <translation>检查更新</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/>
<source>Open &amp;Wizard</source>
- <translation type="unfinished"></translation>
+ <translation>打开和向导</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
<source>Open the wizard</source>
- <translation type="unfinished"></translation>
+ <translation>打开向导</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
<source>Append Selected Key(s) To Text</source>
- <translation type="unfinished"></translation>
+ <translation>将所选密钥附加到文本</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
<source>Append The Selected Keys To Text in Editor</source>
- <translation type="unfinished"></translation>
+ <translation>将所选密钥附加到编辑器中的文本</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/>
- <source>Copy EMail-address</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <source>Copy Email</source>
+ <translation>复制电子邮件</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/>
- <source>Copy selected EMailaddress to clipboard</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <source>Copy selected Email to clipboard</source>
+ <translation>复制所选电子邮件至剪贴板</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
<source>Show Key Details</source>
- <translation type="unfinished"></translation>
+ <translation>显示密钥详情</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/>
<source>Show Details for this Key</source>
- <translation type="unfinished"></translation>
+ <translation>显示此密钥的详细信息</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/>
<source>Refresh Key From Key Server</source>
- <translation type="unfinished"></translation>
+ <translation>从密钥服务器的刷新密钥对</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/>
<source>Refresh key from default key server</source>
- <translation type="unfinished"></translation>
+ <translation>刷新默认密钥服务器的密钥</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/>
<source>Upload Public Key(s) To Server</source>
- <translation type="unfinished"></translation>
+ <translation>将公钥上传到服务器</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/>
<source>Upload The Selected Public Keys To Server</source>
- <translation type="unfinished"></translation>
+ <translation>将所选公钥上传到服务器</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/>
<source>Remove PGP Header</source>
- <translation type="unfinished"></translation>
+ <translation>删除PGP标题</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/>
<source>Add PGP Header</source>
- <translation type="unfinished"></translation>
+ <translation>添加PGP标题</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/>
<source>&amp;File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;文件</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/>
<source>&amp;Edit</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;编辑</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/>
<source>&amp;File...</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;文件...</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/>
<source>&amp;Crypt</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;加密</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
<source>&amp;Keys</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;密钥</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/>
<source>&amp;Import Key</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;导入密钥</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/>
<source>&amp;Steganography</source>
- <translation type="unfinished"></translation>
+ <translation>隐写术</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
<source>&amp;View</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;视图</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/>
<source>&amp;Help</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;帮助</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/>
<source>File</source>
- <translation type="unfinished"></translation>
+ <translation>文件</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/>
<source>Crypt</source>
- <translation type="unfinished"></translation>
+ <translation>加密</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/>
<source>Key</source>
- <translation type="unfinished"></translation>
+ <translation>密钥</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/>
<source>Edit</source>
- <translation type="unfinished"></translation>
+ <translation>编辑</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/>
<source>Special Edit</source>
- <translation type="unfinished"></translation>
+ <translation>特殊编辑操作</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/>
<source>Import key from...</source>
- <translation type="unfinished"></translation>
+ <translation>从...导入密钥</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/>
<source>Import key</source>
- <translation type="unfinished"></translation>
+ <translation>导入密钥</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/>
<source>Browser to view and operate file</source>
- <translation type="unfinished"></translation>
+ <translation>文件查看器用于浏览和操作文件</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/>
<source>Browser</source>
- <translation type="unfinished"></translation>
+ <translation>文件查看器</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/>
<source>Ready</source>
- <translation type="unfinished"></translation>
+ <translation>准备好</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/>
<source>Key ToolBox</source>
- <translation type="unfinished"></translation>
+ <translation>密钥工具箱</translation>
</message>
<message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/>
+ <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/>
<source>Information Board</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/>
- <source>Attached files:</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>MimeTab</name>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
- <source>Decode quoted printable</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="292"/>
- <source>Try to recognize quoted printable.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="296"/>
- <source>Parse PGP/MIME (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="299"/>
- <source>Try to split attachments from PGP-MIME ecrypted messages.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="304"/>
- <source>Open with external application (Experimental)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="306"/>
- <source>Open attachments with default application for the filetype.&lt;br&gt; There are at least two possible problems with this behaviour:&lt;ol&gt;&lt;li&gt;File needs to be saved unencrypted to attachments folder.&lt;br&gt; Its your job to clean this folder.&lt;/li&gt;&lt;li&gt;The external application may have its own temp files.&lt;/li&gt;&lt;/ol&gt;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
- <source>Enable opening with external applications.</source>
- <translation type="unfinished"></translation>
+ <translation>信息板</translation>
</message>
</context>
<context>
@@ -2664,107 +2811,107 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/gpg/result_analyse/DecryptResultAnalyse.cpp" line="42"/>
<source>&gt;Recipient: </source>
- <translation type="unfinished"></translation>
+ <translation>&gt;收件人:</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="35"/>
<source>One or More Bad Signatures.</source>
- <translation type="unfinished"></translation>
+ <translation>一个或多个糟糕的签名。</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="40"/>
<source>A </source>
- <translation type="unfinished"></translation>
+ <translation>一种</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="42"/>
<source>Good </source>
- <translation type="unfinished"></translation>
+ <translation>好的</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="45"/>
<source>Bad </source>
- <translation type="unfinished"></translation>
+ <translation>坏的</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="48"/>
<source>Expired </source>
- <translation type="unfinished"></translation>
+ <translation>已到期</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="51"/>
<source>Missing Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>缺少密钥</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="54"/>
<source>Revoked Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>撤销密钥</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="57"/>
<source>Expired Key&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>过期密钥</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="60"/>
<source>Missing CRL&apos;s </source>
- <translation type="unfinished"></translation>
+ <translation>缺少CRL</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="64"/>
<source>Signature Fully Valid.</source>
- <translation type="unfinished"></translation>
+ <translation>签名完全有效。</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="66"/>
<source>Signature NOT Fully Valid.</source>
- <translation type="unfinished"></translation>
+ <translation>签名无效。</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="74"/>
<source>Key is NOT present with ID 0x</source>
- <translation type="unfinished"></translation>
+ <translation>密钥不存在ID 0x</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="81"/>
<source>A signature could NOT be verified due to a Missing Key
</source>
- <translation type="unfinished"></translation>
+ <translation>由于缺少密钥而无法验证签名</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="85"/>
<source>A signature is valid but the key used to verify the signature has been revoked
</source>
- <translation type="unfinished"></translation>
+ <translation>签名是有效的,但用于验证签名的密钥已被撤销</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="93"/>
<source>A signature is valid but expired
</source>
- <translation type="unfinished"></translation>
+ <translation>签名有效但已过期</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="100"/>
<source>A signature is valid but the key used to verify the signature has expired.
</source>
- <translation type="unfinished"></translation>
+ <translation>签名有效,但用于验证签名的密钥已过期。</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="107"/>
<source>There was some other error which prevented the signature verification.
</source>
- <translation type="unfinished"></translation>
+ <translation>还有一些其他错误阻止了签名验证。</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="113"/>
<source>Error for key with fingerprint </source>
- <translation type="unfinished"></translation>
+ <translation>带指纹的密钥错误</translation>
</message>
<message>
<location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="128"/>
<source>Signed By: </source>
- <translation type="unfinished"></translation>
+ <translation>被...签名:</translation>
</message>
</context>
<context>
@@ -2772,60 +2919,193 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="29"/>
<source>Unsaved Files</source>
- <translation type="unfinished"></translation>
+ <translation>未保存的文件</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="77"/>
- <source>&lt;h3&gt;%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?&lt;/h3&gt;</source>
- <translation type="unfinished"></translation>
+ <source>%1 files contain unsaved information.&lt;br/&gt;Save the changes before closing?</source>
+ <translation>%1文件包含未保存的信息。&lt;br/&gt;在结束前保存更改?</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="88"/>
<source>Check the files you want to save:</source>
- <translation type="unfinished"></translation>
+ <translation>检查要保存的文件:</translation>
</message>
<message>
<location filename="../../src/ui/QuitDialog.cpp" line="89"/>
<source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>&lt;b&gt;注意:&lt;/ b&gt;如果您不保存这些文件,则所有更改都会丢失。&lt;br/&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>SendMailDialog</name>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="35"/>
+ <source>Incomplete configuration</source>
+ <translation>配置不完整</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="36"/>
+ <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source>
+ <translation>SMTP地址为空,请转到设置界面以完成配置。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="86"/>
+ <source> Recipient cannot be empty
+</source>
+ <translation>收件人不能空</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="91"/>
+ <source> One or more Recipient&apos;s Email Address is invalid
+</source>
+ <translation>一个或多个收件人的电子邮件地址无效</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="97"/>
+ <source> Sender cannot be empty
+</source>
+ <translation>发件人不能为空</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="99"/>
+ <source> Sender&apos;s Email Address is invalid
+</source>
+ <translation>发件人的电子邮件地址无效</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail</source>
+ <translation>失败</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="155"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation>无法连接SMTP服务器</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="160"/>
+ <source>Fail to Login into SMTP Server</source>
+ <translation>无法登录SMTP服务器</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="165"/>
+ <source>Fail to Send Mail to SMTP Server</source>
+ <translation>无法将邮件发送到SMTP服务器</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Success</source>
+ <translation>成功</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SendMailDialog.cpp" line="171"/>
+ <source>Succeed in Sending Mail to SMTP Server</source>
+ <translation>成功向SMTP服务器发送邮件</translation>
+ </message>
+</context>
+<context>
+ <name>SendMailTab</name>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="289"/>
+ <source>Enable</source>
+ <translation>使能够</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="311"/>
+ <source>SMTP Address</source>
+ <translation>SMTP地址</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="313"/>
+ <source>Username</source>
+ <translation>用户名</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="315"/>
+ <source>Password</source>
+ <translation>密码</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="317"/>
+ <source>Port</source>
+ <translation>港口</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="319"/>
+ <source>Connection Security</source>
+ <translation>连接安全</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="322"/>
+ <source>Default Sender</source>
+ <translation>默认发件人</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail</source>
+ <translation>失败</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="404"/>
+ <source>Fail to Connect SMTP Server</source>
+ <translation>无法连接SMTP服务器</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="408"/>
+ <source>Fail to Login</source>
+ <translation>未登录</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Success</source>
+ <translation>成功</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="413"/>
+ <source>Succeed in connecting and login</source>
+ <translation>成功连接和登录</translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="38"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
<source>General</source>
- <translation type="unfinished"></translation>
+ <translation>通用</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="39"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
<source>Appearance</source>
- <translation type="unfinished"></translation>
+ <translation>外观</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="40"/>
- <source>PGP/Mime</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="42"/>
+ <source>Send Mail</source>
+ <translation>发送邮件</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="41"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
<source>Key Server</source>
- <translation type="unfinished"></translation>
+ <translation>密钥服务器</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="43"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="45"/>
<source>Advanced</source>
- <translation type="unfinished"></translation>
+ <translation>高级</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="56"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="58"/>
<source>Settings</source>
- <translation type="unfinished"></translation>
+ <translation>设置</translation>
</message>
<message>
- <location filename="../../src/ui/SettingsDialog.cpp" line="101"/>
+ <location filename="../../src/ui/SettingsDialog.cpp" line="103"/>
<source>System Default</source>
- <translation type="unfinished"></translation>
+ <translation>系统默认值</translation>
</message>
</context>
<context>
@@ -2833,62 +3113,62 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="46"/>
<source>Generate New Subkey</source>
- <translation type="unfinished"></translation>
+ <translation>生成新的子项</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="61"/>
<source>Encryption</source>
- <translation type="unfinished"></translation>
+ <translation>加密</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="64"/>
<source>Signing</source>
- <translation type="unfinished"></translation>
+ <translation>签名</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="67"/>
<source>Certification</source>
- <translation type="unfinished"></translation>
+ <translation>认证</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="70"/>
<source>Authentication</source>
- <translation type="unfinished"></translation>
+ <translation>验证</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="114"/>
<source>Expiration Date:</source>
- <translation type="unfinished"></translation>
+ <translation>过期日期:</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="115"/>
<source>Never Expire</source>
- <translation type="unfinished"></translation>
+ <translation>永不过期</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="116"/>
<source>KeySize (in Bit):</source>
- <translation type="unfinished"></translation>
+ <translation>keysize(位):</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="117"/>
<source>Key Type:</source>
- <translation type="unfinished"></translation>
+ <translation>密钥类型:</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="126"/>
<source>Basic Information</source>
- <translation type="unfinished"></translation>
+ <translation>基本信息</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="214"/>
<source> Expiration time no more than 2 years. </source>
- <translation type="unfinished"></translation>
+ <translation>到期时间不超过2年。</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="235"/>
<source>Generating Subkey...</source>
- <translation type="unfinished"></translation>
+ <translation>生成子密钥......</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="238"/>
@@ -2896,90 +3176,129 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
This may take a while.
To speed up the process use your computer
(e.g. browse the net, listen to music,...)</source>
- <translation type="unfinished"></translation>
+ <translation>收集子项的随机数据。
+ 可能还要等一下。
+ 加快过程使用您的计算机
+ (例如,浏览网,听音乐,......)</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/>
<source>Success</source>
- <translation type="unfinished"></translation>
+ <translation>成功</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/>
<source>The new subkey has been generated.</source>
- <translation type="unfinished"></translation>
+ <translation>已生成新的子项。</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/>
<source>Failure</source>
- <translation type="unfinished"></translation>
+ <translation>失败</translation>
</message>
<message>
<location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/>
<source>An error occurred during subkey generation.</source>
- <translation type="unfinished"></translation>
+ <translation>子项生成期间发生错误。</translation>
</message>
</context>
<context>
<name>TextEdit</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/>
<source>untitled</source>
- <translation type="unfinished"></translation>
+ <translation>无标题</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>警告</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/>
+ <source>Cannot read file %1:
+%2.</source>
+ <translation>无法读取文件%1:
+%2。</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/>
<source>Open file</source>
- <translation type="unfinished"></translation>
+ <translation>打开文件</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/>
+ <source>File</source>
+ <translation>文件</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/>
+ <source>Cannot write file %1:
+%2.</source>
+ <translation>无法写入文件%1:
+%2。</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
<source>Save file</source>
- <translation type="unfinished"></translation>
+ <translation>保存存档</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/>
+ <source>Unsaved document</source>
+ <translation>未保存的文件</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/>
+ <source>The document &quot;%1&quot; has been modified. Do you want to save your changes?&lt;br/&gt;</source>
+ <translation>文档“%1”已被修改。你想保存你的更改吗?&lt;br/&gt;</translation>
+ </message>
+ <message>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/>
+ <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
+ <translation>&lt;b&gt;注意:&lt;/ b&gt;如果您不保存这些文件,则所有更改都会丢失。&lt;br/&gt;</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/>
+ <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/>
<source>Application</source>
- <translation type="unfinished"></translation>
+ <translation>应用</translation>
</message>
+</context>
+<context>
+ <name>UpdateTab</name>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/>
- <source>Cannot read file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/>
+ <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source>
+ <translation>建议您始终检查GPGFrontend的版本并升级到最新版本。</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/>
- <source>File</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/>
+ <source>New versions not only represent new features, but also often represent functional and security fixes.</source>
+ <translation>新版本不仅代表新功能,而且通常代表功能和安全修复。</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/>
- <source>Cannot write file %1:
-%2.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/>
+ <source>Current Version: </source>
+ <translation>当前版本:</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/>
- <source>Unsaved document</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/>
+ <source>The current version is inconsistent with the latest version on github.</source>
+ <translation>当前版本与GitHub上的最新版本不一致。</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/>
- <source>&lt;h3&gt;The document &quot;%1&quot; has been modified.&lt;br/&gt;Do you want to save your changes?&lt;/h3&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/>
+ <source>Please click &lt;a href=&quot;https://github.com/saturneric/GpgFrontend/releases&quot;&gt;here&lt;/a&gt; to download the latest version.</source>
+ <translation>请单击&lt;a href=&quot;https://github.com/saturneric/gpgfrontend/releases&quot;&gt;此处&lt;/a&gt;下载最新版本。</translation>
</message>
<message>
- <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/>
- <source>&lt;b&gt;Note:&lt;/b&gt; If you don&apos;t save these files, all changes are lost.&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/>
+ <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/>
+ <source>Latest Version From Github: </source>
+ <translation>GitHub的最新版本:</translation>
</message>
</context>
<context>
@@ -2987,32 +3306,32 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="32"/>
<source>Signature Details</source>
- <translation type="unfinished"></translation>
+ <translation>签名细节</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="53"/>
<source>Status: </source>
- <translation type="unfinished"></translation>
+ <translation>状态:</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="56"/>
<source>No valid input found</source>
- <translation type="unfinished"></translation>
+ <translation>没有找到有效的输入</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="67"/>
<source>Error Validating signature</source>
- <translation type="unfinished"></translation>
+ <translation>验证签名时出错</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="70"/>
<source>File was signed on %1 &lt;br/&gt; It Contains:&lt;br/&gt;&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>文件已签名%1 &lt;br/&gt; &lt;br/&gt; &lt;br/&gt;</translation>
</message>
<message>
<location filename="../../src/ui/VerifyDetailsDialog.cpp" line="72"/>
<source>Signed on %1 &lt;br/&gt; It Contains:&lt;br /&gt;&lt;br/&gt;</source>
- <translation type="unfinished"></translation>
+ <translation>签名%1 &lt;br/&gt;它包含:&lt;br /&gt; &lt;br/&gt;</translation>
</message>
</context>
<context>
@@ -3020,22 +3339,22 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="36"/>
<source>Import from keyserver</source>
- <translation type="unfinished"></translation>
+ <translation>从密钥服务器导入</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="39"/>
<source>Key not present with id 0x</source>
- <translation type="unfinished"></translation>
+ <translation>密钥不存在ID 0x</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="43"/>
<source>Status:</source>
- <translation type="unfinished"></translation>
+ <translation>地位:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="45"/>
<source>Key not present in keylist</source>
- <translation type="unfinished"></translation>
+ <translation>密钥不存在于keylist</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="58"/>
@@ -3045,7 +3364,7 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="115"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="129"/>
<source>Key Information is NOT Available</source>
- <translation type="unfinished"></translation>
+ <translation>密钥信息不可用</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="60"/>
@@ -3055,103 +3374,103 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="117"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="131"/>
<source>Fingerprint: </source>
- <translation type="unfinished"></translation>
+ <translation>指纹:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="67"/>
<source>Status: Cert Revoked</source>
- <translation type="unfinished"></translation>
+ <translation>状态:证书撤销</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="81"/>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="95"/>
<source>Status: Signature Expired</source>
- <translation type="unfinished"></translation>
+ <translation>状态:签名已过期</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="96"/>
<source>Status: Key Expired</source>
- <translation type="unfinished"></translation>
+ <translation>状态:密钥已过期</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="110"/>
<source>Status: General Error</source>
- <translation type="unfinished"></translation>
+ <translation>状态:一般错误</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="124"/>
<source>Status: Unknown Error</source>
- <translation type="unfinished"></translation>
+ <translation>状态:未知错误</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="159"/>
<source>Signer Name:</source>
- <translation type="unfinished"></translation>
+ <translation>签名者名称:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="160"/>
<source>Signer Email:</source>
- <translation type="unfinished"></translation>
+ <translation>签名电子邮件:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="161"/>
<source>Key&apos;s Fingerprint:</source>
- <translation type="unfinished"></translation>
+ <translation>密钥的指纹:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="162"/>
<source>Valid:</source>
- <translation type="unfinished"></translation>
+ <translation>有效的:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="163"/>
<source>Flags:</source>
- <translation type="unfinished"></translation>
+ <translation>标志:</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="171"/>
<source>Fully Valid</source>
- <translation type="unfinished"></translation>
+ <translation>完全有效</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="173"/>
<source>NOT Fully Valid</source>
- <translation type="unfinished"></translation>
+ <translation>没有完全有效</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="180"/>
<source>Good </source>
- <translation type="unfinished"></translation>
+ <translation>好的</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="183"/>
<source>Bad </source>
- <translation type="unfinished"></translation>
+ <translation>坏的</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="186"/>
<source>Expired </source>
- <translation type="unfinished"></translation>
+ <translation>已到期</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="189"/>
<source>Missing Key </source>
- <translation type="unfinished"></translation>
+ <translation>缺少密钥</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="192"/>
<source>Revoked Key </source>
- <translation type="unfinished"></translation>
+ <translation>撤销密钥</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="195"/>
<source>Expired Key </source>
- <translation type="unfinished"></translation>
+ <translation>过期的密钥</translation>
</message>
<message>
<location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="198"/>
<source>Missing CRL </source>
- <translation type="unfinished"></translation>
+ <translation>缺少CRL.</translation>
</message>
</context>
<context>
@@ -3159,33 +3478,33 @@ This is NOT your Public Key, so DON&apos;T give it away.&lt;br /&gt;Do you REALL
<message>
<location filename="../../src/ui/Wizard.cpp" line="46"/>
<source>First Start Wizard</source>
- <translation type="unfinished"></translation>
+ <translation>首次开始向导</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="76"/>
<source>Import Error</source>
- <translation type="unfinished"></translation>
+ <translation>导入错误</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="76"/>
<source>Couldn&apos;t locate any keyring file in %1</source>
- <translation type="unfinished"></translation>
+ <translation>无法在%1中定位任何密钥控文件</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="84"/>
<location filename="../../src/ui/Wizard.cpp" line="95"/>
<source>Import error</source>
- <translation type="unfinished"></translation>
+ <translation>导入错误</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="85"/>
<source>Couldn&apos;t open private keyringfile: %1</source>
- <translation type="unfinished"></translation>
+ <translation>无法打开私有keyringfile:%1</translation>
</message>
<message>
<location filename="../../src/ui/Wizard.cpp" line="96"/>
<source>Couldn&apos;t open public keyringfile: %1</source>
- <translation type="unfinished"></translation>
+ <translation>无法打开公钥密钥入文件:%1</translation>
</message>
</context>
</TS>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0d1336ba..ad56423d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,6 +2,7 @@ set(ALL_SOURCE_FILE)
add_subdirectory(gpg)
add_subdirectory(ui)
+add_subdirectory(smtp)
aux_source_directory(. BASE_SOURCE)
@@ -23,6 +24,8 @@ if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
elseif(LINUX)
file(COPY ${CMAKE_SOURCE_DIR}/resource/gpgfrontend DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN)
set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gpgfrontend/usr/share)
+ else()
+ set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif()
else()
set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
@@ -33,7 +36,9 @@ message(STATUS "RESOURCE_OUTPUT_DIRECTORY ${RESOURCE_OUTPUT_DIRECTORY}")
file(GLOB_RECURSE ALL_SOURCE_FILES RELACTIVE ${CMAKE_SOURCE_DIR}/src/*.cpp)
# Set Translation Files
-set(QT_TS_FILES gpgfrontend_en_us.ts gpgfrontend_zh_chs.ts gpgfrontend_zh_cht.ts gpg_frontend_fr.ts gpg_frontend_ru.ts)
+set(QT_TS_FILES
+ gpgfrontend_en_us.ts gpgfrontend_zh_cn.ts
+ gpgfrontend_fr.ts gpgfrontend_ru.ts gpgfrontend_es.ts)
list(TRANSFORM QT_TS_FILES PREPEND ${CMAKE_SOURCE_DIR}/resource/ts/)
message(STATUS "QT_TS_FILES ${QT_TS_FILES}")
set(QT_QM_FILES_OUTPUT_DIR ${RESOURCE_OUTPUT_DIRECTORY}/ts)
@@ -44,6 +49,7 @@ add_custom_target(translations DEPENDS ${QON_QM_FILES})
# Set Build Information
configure_file(${CMAKE_SOURCE_DIR}/include/GpgFrontend.h.in ${CMAKE_SOURCE_DIR}/include/GpgFrontend.h @ONLY)
+configure_file(${CMAKE_SOURCE_DIR}/include/GpgFrontendBuildInfo.h.in ${CMAKE_SOURCE_DIR}/include/GpgFrontendBuildInfo.h @ONLY)
# Copy Resource Files
file(COPY ${CMAKE_SOURCE_DIR}/resource/css DESTINATION ${RESOURCE_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN)
@@ -118,19 +124,19 @@ endif()
IF (MINGW)
message(STATUS "Link Application Static Library For MINGW")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl)
elseif(APPLE)
message(STATUS "Link Application Static Library For macOS")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl)
else()
message(STATUS "Link Application Static Library For UNIX")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl pthread)
endif()
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index a59bd01d..eb8b96b1 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -23,208 +23,223 @@
*/
#include "MainWindow.h"
+#include "ui/help/VersionCheckThread.h"
MainWindow::MainWindow()
- : appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
-
- auto waitingDialog = new WaitingDialog(this);
-
- auto ctx_thread = QThread::create([&]() { mCtx = new GpgME::GpgContext(); });
-
- ctx_thread->start();
-
- while (ctx_thread->isRunning())
- QApplication::processEvents();
-
- waitingDialog->close();
-
-
- if (!mCtx->isGood()) {
- QMessageBox::critical(
- nullptr, tr("ENV Loading Failed"),
- tr("Gnupg is not installed correctly, please follow the ReadME "
- "instructions to install gnupg and then open GPGFrontend."));
- QCoreApplication::quit();
- exit(0);
- }
-
- /* get path were app was started */
- setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
- setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
-
- qDebug() << "Main Window" << this;
-
- edit = new TextEdit(this);
- setCentralWidget(edit);
-
- /* the list of Keys available*/
- mKeyList = new KeyList(mCtx, KeyListRow::SECRET_OR_PUBLIC_KEY,
- KeyListColumn::TYPE | KeyListColumn::NAME |
- KeyListColumn::EmailAddress |
- KeyListColumn::Usage | KeyListColumn::Validity,
- this);
- mKeyList->setFilter([](const GpgKey &key) -> bool {
- if (key.revoked || key.disabled || key.expired)
- return false;
- else
- return true;
- });
- mKeyList->slotRefresh();
-
- infoBoard = new InfoBoardWidget(this, mCtx, mKeyList);
-
- /* List of binary Attachments */
- attachmentDockCreated = false;
-
- /* Variable containing if restart is needed */
- this->slotSetRestartNeeded(false);
-
- keyMgmt = new KeyMgmt(mCtx, this);
- keyMgmt->hide();
- /* test attachmentdir for files alll 15s */
- auto *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder()));
- timer->start(5000);
-
- createActions();
- createMenus();
- createToolBars();
- createStatusBar();
- createDockWindows();
-
- connect(edit->tabWidget, SIGNAL(currentChanged(int)), this,
- SLOT(slotDisableTabActions(int)));
-
- mKeyList->addMenuAction(appendSelectedKeysAct);
- mKeyList->addMenuAction(copyMailAddressToClipboardAct);
- mKeyList->addMenuAction(showKeyDetailsAct);
- mKeyList->addMenuAction(refreshKeysFromKeyserverAct);
- mKeyList->addMenuAction(uploadKeyToServerAct);
-
- restoreSettings();
-
- // open filename if provided as first command line parameter
- QStringList args = qApp->arguments();
- if (args.size() > 1) {
- if (!args[1].startsWith("-")) {
- if (QFile::exists(args[1]))
- edit->loadFile(args[1]);
+ : appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+
+ networkAccessManager = new QNetworkAccessManager(this);
+
+ auto waitingDialog = new WaitingDialog(tr("Loading Gnupg"), this);
+
+ // Init Gnupg
+ auto ctx_thread = QThread::create([&]() { mCtx = new GpgME::GpgContext(); });
+ ctx_thread->start();
+ while (ctx_thread->isRunning())
+ QApplication::processEvents();
+ waitingDialog->close();
+ ctx_thread->deleteLater();
+
+ QString baseUrl = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest";
+
+ QNetworkRequest request;
+ request.setUrl(QUrl(baseUrl));
+
+ QNetworkReply *replay = networkAccessManager->get(request);
+
+ auto version_thread = new VersionCheckThread(replay);
+
+ connect(version_thread, SIGNAL(finished(QPrivateSignal)), version_thread, SLOT(deleteLater()));
+ connect(version_thread, SIGNAL(upgradeVersion(const QString &, const QString &)), this, SLOT(slotVersionUpgrade(const QString &, const QString &)));
+
+ version_thread->start();
+
+ // Check Context Status
+ if (!mCtx->isGood()) {
+ QMessageBox::critical(
+ nullptr, tr("ENV Loading Failed"),
+ tr("Gnupg is not installed correctly, please follow the ReadME "
+ "instructions to install gnupg and then open GPGFrontend."));
+ QCoreApplication::quit();
+ exit(0);
+ }
+
+ /* get path were app was started */
+ setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+ setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+
+ edit = new TextEdit(this);
+ setCentralWidget(edit);
+
+ /* the list of Keys available*/
+ mKeyList = new KeyList(mCtx, KeyListRow::SECRET_OR_PUBLIC_KEY,
+ KeyListColumn::TYPE | KeyListColumn::NAME |
+ KeyListColumn::EmailAddress |
+ KeyListColumn::Usage | KeyListColumn::Validity,
+ this);
+ mKeyList->setFilter([](const GpgKey &key) -> bool {
+ if (key.revoked || key.disabled || key.expired)
+ return false;
+ else
+ return true;
+ });
+ mKeyList->slotRefresh();
+
+ infoBoard = new InfoBoardWidget(this, mCtx, mKeyList);
+
+ /* List of binary Attachments */
+ attachmentDockCreated = false;
+
+ /* Variable containing if restart is needed */
+ this->slotSetRestartNeeded(false);
+
+ keyMgmt = new KeyMgmt(mCtx, this);
+ keyMgmt->hide();
+ /* test attachmentdir for files alll 15s */
+ auto *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder()));
+ timer->start(5000);
+
+ createActions();
+ createMenus();
+ createToolBars();
+ createStatusBar();
+ createDockWindows();
+
+ connect(edit->tabWidget, SIGNAL(currentChanged(int)), this,
+ SLOT(slotDisableTabActions(int)));
+
+ mKeyList->addMenuAction(appendSelectedKeysAct);
+ mKeyList->addMenuAction(copyMailAddressToClipboardAct);
+ mKeyList->addMenuAction(showKeyDetailsAct);
+ mKeyList->addSeparator();
+ mKeyList->addMenuAction(refreshKeysFromKeyserverAct);
+ mKeyList->addMenuAction(uploadKeyToServerAct);
+
+ restoreSettings();
+
+ // open filename if provided as first command line parameter
+ QStringList args = qApp->arguments();
+ if (args.size() > 1) {
+ if (!args[1].startsWith("-")) {
+ if (QFile::exists(args[1]))
+ edit->loadFile(args[1]);
+ }
+ }
+ edit->curTextPage()->setFocus();
+ this->setMinimumSize(1200, 700);
+ this->setWindowTitle(qApp->applicationName());
+ this->show();
+
+ // Show wizard, if the don't show wizard message box wasn't checked
+ // and keylist doesn't contain a private key
+ qDebug() << "wizard/showWizard"
+ << settings.value("wizard/showWizard", true).toBool();
+ qDebug() << "wizard/nextPage" << settings.value("wizard/nextPage").isNull();
+ if (settings.value("wizard/showWizard", true).toBool() ||
+ !settings.value("wizard/nextPage").isNull()) {
+ slotStartWizard();
}
- }
- edit->curTextPage()->setFocus();
- this->setMinimumSize(1200, 700);
- this->setWindowTitle(qApp->applicationName());
- this->show();
-
- // Show wizard, if the don't show wizard message box wasn't checked
- // and keylist doesn't contain a private key
- qDebug() << "wizard/showWizard"
- << settings.value("wizard/showWizard", true).toBool();
- qDebug() << "wizard/nextPage" << settings.value("wizard/nextPage").isNull();
- if (settings.value("wizard/showWizard", true).toBool() ||
- !settings.value("wizard/nextPage").isNull()) {
- slotStartWizard();
- }
}
void MainWindow::restoreSettings() {
- // state sets pos & size of dock-widgets
- this->restoreState(settings.value("window/windowState").toByteArray());
-
- // Restore window size & location
- if (settings.value("window/windowSave").toBool()) {
- QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint();
- QSize size = settings.value("window/size", QSize(800, 450)).toSize();
- this->resize(size);
- this->move(pos);
- } else {
- this->resize(QSize(800, 450));
- this->move(QPoint(100, 100));
- }
-
- // Iconsize
- QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
- this->setIconSize(iconSize);
-
- importButton->setIconSize(iconSize);
- fileEncButton->setIconSize(iconSize);
- // set list of keyserver if not defined
- QStringList *keyServerDefaultList;
- keyServerDefaultList = new QStringList("http://keys.gnupg.net");
- keyServerDefaultList->append("https://keyserver.ubuntu.com");
- keyServerDefaultList->append("http://pool.sks-keyservers.net");
-
- QStringList keyServerList =
- settings.value("keyserver/keyServerList", *keyServerDefaultList)
- .toStringList();
- settings.setValue("keyserver/keyServerList", keyServerList);
-
- // set default keyserver, if it's not set
- QString defaultKeyServer = settings
- .value("keyserver/defaultKeyServer",
- QString("https://keyserver.ubuntu.com"))
- .toString();
- settings.setValue("keyserver/defaultKeyServer", defaultKeyServer);
-
- // Iconstyle
- Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(
- settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
- .toUInt());
- this->setToolButtonStyle(buttonStyle);
- importButton->setToolButtonStyle(buttonStyle);
- fileEncButton->setToolButtonStyle(buttonStyle);
-
- // Checked Keys
- if (settings.value("keys/saveKeyChecked").toBool()) {
- QStringList keyIds =
- settings.value("keys/savedCheckedKeyList").toStringList();
- mKeyList->setChecked(&keyIds);
- }
+ // state sets pos & size of dock-widgets
+ this->restoreState(settings.value("window/windowState").toByteArray());
+
+ // Restore window size & location
+ if (settings.value("window/windowSave").toBool()) {
+ QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint();
+ QSize size = settings.value("window/size", QSize(800, 450)).toSize();
+ this->resize(size);
+ this->move(pos);
+ } else {
+ this->resize(QSize(800, 450));
+ this->move(QPoint(100, 100));
+ }
+
+ // Iconsize
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
+ this->setIconSize(iconSize);
+
+ importButton->setIconSize(iconSize);
+ fileEncButton->setIconSize(iconSize);
+ // set list of keyserver if not defined
+ QStringList *keyServerDefaultList;
+ keyServerDefaultList = new QStringList("http://keys.gnupg.net");
+ keyServerDefaultList->append("https://keyserver.ubuntu.com");
+ keyServerDefaultList->append("http://pool.sks-keyservers.net");
+
+ QStringList keyServerList =
+ settings.value("keyserver/keyServerList", *keyServerDefaultList)
+ .toStringList();
+ settings.setValue("keyserver/keyServerList", keyServerList);
+
+ // set default keyserver, if it's not set
+ QString defaultKeyServer = settings
+ .value("keyserver/defaultKeyServer",
+ QString("https://keyserver.ubuntu.com"))
+ .toString();
+ settings.setValue("keyserver/defaultKeyServer", defaultKeyServer);
+
+ // Iconstyle
+ Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(
+ settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
+ .toUInt());
+ this->setToolButtonStyle(buttonStyle);
+ importButton->setToolButtonStyle(buttonStyle);
+ fileEncButton->setToolButtonStyle(buttonStyle);
+
+ // Checked Keys
+ if (settings.value("keys/saveKeyChecked").toBool()) {
+ QStringList keyIds =
+ settings.value("keys/savedCheckedKeyList").toStringList();
+ mKeyList->setChecked(&keyIds);
+ }
}
void MainWindow::saveSettings() {
- // window position and size
- settings.setValue("window/windowState", saveState());
- settings.setValue("window/pos", pos());
- settings.setValue("window/size", size());
-
- // keyid-list of private checked keys
- if (settings.value("keys/saveKeyChecked").toBool()) {
- QStringList *keyIds = mKeyList->getChecked();
- if (!keyIds->isEmpty()) {
- settings.setValue("keys/savedCheckedKeyList", *keyIds);
+ // window position and size
+ settings.setValue("window/windowState", saveState());
+ settings.setValue("window/pos", pos());
+ settings.setValue("window/size", size());
+
+ // keyid-list of private checked keys
+ if (settings.value("keys/saveKeyChecked").toBool()) {
+ QStringList *keyIds = mKeyList->getChecked();
+ if (!keyIds->isEmpty()) {
+ settings.setValue("keys/savedCheckedKeyList", *keyIds);
+ } else {
+ settings.setValue("keys/savedCheckedKeyList", "");
+ }
} else {
- settings.setValue("keys/savedCheckedKeyList", "");
+ settings.remove("keys/savedCheckedKeyList");
}
- } else {
- settings.remove("keys/savedCheckedKeyList");
- }
}
void MainWindow::closeAttachmentDock() {
- if (!attachmentDockCreated) {
- return;
- }
- attachmentDock->close();
- attachmentDock->deleteLater();
- attachmentDockCreated = false;
+ if (!attachmentDockCreated) {
+ return;
+ }
+ attachmentDock->close();
+ attachmentDock->deleteLater();
+ attachmentDockCreated = false;
}
void MainWindow::closeEvent(QCloseEvent *event) {
- /*
- * ask to save changes, if there are
- * modified documents in any tab
- */
- if (edit->maybeSaveAnyTab()) {
- saveSettings();
- event->accept();
- } else {
- event->ignore();
- }
-
- // clear password from memory
- mCtx->clearPasswordCache();
+ /*
+ * ask to save changes, if there are
+ * modified documents in any tab
+ */
+ if (edit->maybeSaveAnyTab()) {
+ saveSettings();
+ event->accept();
+ } else {
+ event->ignore();
+ }
+
+ // clear password from memory
+ mCtx->clearPasswordCache();
}
diff --git a/src/Mime.cpp b/src/Mime.cpp
deleted file mode 100644
index 8e4c8d72..00000000
--- a/src/Mime.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-/* TODO: proper import / copyright statement
- *
- */
-
-#include "Mime.h"
-
-Mime::Mime(QByteArray *message) {
- splitParts(message);
- /*
- mMessage = message;
- int bStart = mMessage->indexOf("boundary=\"") + 10 ;
- int bEnd = mMessage->indexOf("\"\n", bStart );
-
- qDebug() << "bStart: " << bStart << " bEnd: " << bEnd;
- mBoundary = new QByteArray(mMessage->mid(bStart, bEnd - bStart));
- qDebug() << "boundary: " << *mBoundary;
-
- Part *p1 = new Part();
-
- int nb = mMessage->indexOf(*mBoundary, bEnd) + mBoundary->length() +1 ;
- qDebug() << "nb: " << nb;
- int eh = mMessage->indexOf("\n\n", nb);
- qDebug() << "eh: " << eh;
- QByteArray *header = new QByteArray(mMessage->mid(nb , eh - nb));
- qDebug() << "header:" << header;
-
- // split header at newlines
- foreach(QByteArray tmp , header->split(* "\n")) {
- // split lines at :
- QList<QByteArray> tmp2 = tmp.split(* ":");
- p1->header.insert(QString(tmp2[0].trimmed()), QString(tmp2[1].trimmed()));
- }
-
- QHashIterator<QString, QString> i(p1->header);
- while (i.hasNext()) {
- i.next();
- qDebug() << "found: " << i.key() << ":" << i.value() << endl;
- }
-
- int nb2 = mMessage->indexOf(*mBoundary, eh);
-
- p1->body = mMessage->mid(eh , nb2 - eh);
-
- QTextCodec *codec = QTextCodec::codecForName("ISO-8859-15");
- QString qs = codec->toUnicode(p1->body);
- qDebug() << "body: " << qs;
- */
-}
-
-Mime::~Mime()
-= default;
-
-void Mime::splitParts(QByteArray *message) {
- int pos1, pos2, headEnd;
- MimePart p_tmp;
-
- // find the boundary
- pos1 = message->indexOf("boundary=\"") + 10;
- pos2 = message->indexOf("\"\n", pos1);
- QByteArray boundary = message->mid(pos1, pos2 - pos1);
- //qDebug() << "boundary: " << boundary;
-
- while (pos2 > pos1) {
-
- pos1 = message->indexOf(boundary, pos2) + boundary.length() + 1;
- headEnd = message->indexOf("\n\n", pos1);
- if (headEnd < 0)
- break;
- QByteArray header = message->mid(pos1, headEnd - pos1);
-
- p_tmp.header = parseHeader(&header);
-
- pos2 = message->indexOf(boundary, headEnd);
- p_tmp.body = message->mid(headEnd, pos2 - headEnd);
-
- mPartList.append(p_tmp);
- }
-}
-
-Header Mime::parseHeader(QByteArray *header) {
-
- QList<HeadElem> ret;
-
- /** http://www.aspnetmime.com/help/welcome/overviewmimeii.html :
- * If a line starts with any white space, that line is said to be 'folded' and is actually
- * part of the header above it.
- */
- header->replace("\n ", " ");
-
- //split header at newlines
- foreach(QByteArray line, header->split(*"\n")) {
- HeadElem elem;
- //split lines at :
- QList<QByteArray> tmp2 = line.split(*":");
- elem.name = tmp2[0].trimmed();
- if (tmp2[1].contains(';')) {
- // split lines at ;
- // TODO: what if ; is inside ""
- QList<QByteArray> tmp3 = tmp2[1].split(*";");
- elem.value = QString(tmp3.takeFirst().trimmed());
- foreach(QByteArray tmp4, tmp3) {
- QList<QByteArray> tmp5 = tmp4.split(*"=");
- elem.params.insert(QString(tmp5[0].trimmed()), QString(tmp5[1].trimmed()));
- }
- } else {
- elem.value = tmp2[1].trimmed();
- }
- ret.append(elem);
- }
- return Header(ret);
-}
-
-Header Mime::getHeader(const QByteArray *message) {
- int headEnd = message->indexOf("\n\n");
- QByteArray header = message->mid(0, headEnd);
- return parseHeader(&header);
-}
-
-bool Mime::isMultipart(QByteArray *message) {
- return message->startsWith("Content-Type: multipart/mixed;");
-}
-
-/**
- * if Content-Type is specified, it should be mime
- *
- */
-bool Mime::isMime(const QByteArray *message) {
- return message->startsWith("Content-Type:");
-}
-
-/***
- * quotedPrintableDecode copied from KCodecs, where it is stated:
-
- The quoted-printable codec as described in RFC 2045, section 6.7. is by
- Rik Hemsley (C) 2001.
-
- */
-
-static const char hexChars[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-/******************************** KCodecs ********************************/
-// strchr(3) for broken systems.
-static int rikFindChar(const char *_s, const char c) {
- const char *s = _s;
-
- while (true) {
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- }
-
- return static_cast<int>(s - _s);
-}
-
-void Mime::quotedPrintableDecode(const QByteArray &in, QByteArray &out) {
- // clear out the output buffer
- out.resize(0);
- if (in.isEmpty())
- return;
-
- char *cursor;
- const char *data;
- const size_t length = in.size();
-
- data = in.data();
- out.resize(static_cast<int>(length));
- cursor = out.data();
-
- for (unsigned int i = 0; i < length; i++) {
- char c(in[i]);
-
- if ('=' == c) {
- if (i < length - 2) {
- char c1 = in[i + 1];
- char c2 = in[i + 2];
-
- if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) {
- // Soft line break. No output.
- if ('\r' == c1)
- i += 2; // CRLF line breaks
- else
- i += 1;
- } else {
- // =XX encoded byte.
-
- int hexChar0 = rikFindChar(hexChars, c1);
- int hexChar1 = rikFindChar(hexChars, c2);
-
- if (hexChar0 < 16 && hexChar1 < 16) {
- *cursor++ = char((hexChar0 * 16) | hexChar1);
- i += 2;
- }
- }
- }
- } else {
- *cursor++ = c;
- }
- }
-
- out.truncate(static_cast<int>(cursor - out.data()));
-}
diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp
index e94ce1ab..0462433d 100644
--- a/src/gpg/GpgContext.cpp
+++ b/src/gpg/GpgContext.cpp
@@ -24,8 +24,8 @@
#include "gpg/GpgContext.h"
+#include <functional>
#include <unistd.h> /* contains read/write */
-#include <Mime.h>
#ifdef _WIN32
@@ -73,8 +73,10 @@ namespace GpgME {
<< engineInfo->home_dir << engineInfo->version;
if (engineInfo->protocol == GPGME_PROTOCOL_GPGCONF && strcmp(engineInfo->version, "1.0.0") != 0)
find_gpgconf = true;
- if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && strcmp(engineInfo->version, "1.0.0") != 0)
+ if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && strcmp(engineInfo->version, "1.0.0") != 0) {
+ gpgExec = engineInfo->file_name;
find_openpgp = true;
+ }
if (engineInfo->protocol == GPGME_PROTOCOL_CMS && strcmp(engineInfo->version, "1.0.0") != 0)
find_cms = true;
if (engineInfo->protocol == GPGME_PROTOCOL_ASSUAN)
@@ -430,38 +432,6 @@ namespace GpgME {
return err;
}
-
- /**
- * if this is mime, split text and attachments...
- * message contains only text afterwards
- */
- void parseMime(QByteArray *message) {
-
- QString pText;
- bool show_ma_dock = false;
-
- Mime *mime = new Mime(message);
- for (MimePart tmp : mime->parts()) {
- if (tmp.header.getValue("Content-Type") == "text/plain" &&
- tmp.header.getValue("Content-Transfer-Encoding") != "base64") {
- QByteArray body;
- if (tmp.header.getValue("Content-Transfer-Encoding") == "quoted-printable") {
- Mime::quotedPrintableDecode(tmp.body, body);
- } else {
- body = tmp.body;
- }
- pText.append(QString(body));
- } else {
- // TODO
- show_ma_dock = true;
- }
- }
- *message = pText.toUtf8();
- if (show_ma_dock) {
- // TODO
- }
- }
-
/** Decrypt QByteAarray, return QByteArray
* mainly from http://basket.kde.org/ (kgpgme.cpp)
*/
@@ -496,28 +466,6 @@ namespace GpgME {
gpgme_data_release(dataOut);
}
- /*
- * 1) is it mime (content-type:)
- * 2) parse header
- * 2) choose action depending on content-type
- */
- if (Mime::isMime(outBuffer)) {
- Header header = Mime::getHeader(outBuffer);
- // is it multipart, is multipart-parsing enabled
- if (header.getValue("Content-Type") == "multipart/mixed"
- && settings.value("mime/parseMime").toBool()) {
- parseMime(outBuffer);
- } else if (header.getValue("Content-Type") == "text/plain"
- && settings.value("mime/parseQP").toBool()) {
- if (header.getValue("Content-Transfer-Encoding") == "quoted-printable") {
- auto *decoded = new QByteArray();
- Mime::quotedPrintableDecode(*outBuffer, *decoded);
- //TODO: remove header
- outBuffer = decoded;
- }
- }
- }
-
if (result != nullptr) {
*result = m_result;
}
@@ -659,16 +607,16 @@ namespace GpgME {
bool GpgContext::exportSecretKey(const GpgKey &key, QByteArray *outBuffer) {
qDebug() << "Export Secret Key" << key.id;
gpgme_key_t target_key[2] = {
- key.key_refer,
- nullptr
+ key.key_refer,
+ nullptr
};
gpgme_data_t dataOut;
gpgme_data_new(&dataOut);
// export private key to outBuffer
- gpgme_error_t error = gpgme_op_export_keys(mCtx, target_key,GPGME_EXPORT_MODE_SECRET, dataOut);
+ gpgme_error_t error = gpgme_op_export_keys(mCtx, target_key, GPGME_EXPORT_MODE_SECRET, dataOut);
- if(gpgme_err_code(error) != GPG_ERR_NO_ERROR) {
+ if (gpgme_err_code(error) != GPG_ERR_NO_ERROR) {
checkErr(error);
gpgme_data_release(dataOut);
return false;
@@ -680,20 +628,31 @@ namespace GpgME {
}
/** return type should be gpgme_error_t*/
- void GpgContext::executeGpgCommand(const QStringList &arguments, QByteArray *stdOut, QByteArray *stdErr) {
+ QProcess * GpgContext::executeGpgCommand(const QStringList &arguments, QByteArray *stdOut, QByteArray *stdErr,
+ const std::function<void(QProcess *)> &interactFunc) {
QStringList args;
- args << "--homedir" << gpgKeys << "--batch" << arguments;
+ args << arguments;
+
+ auto *gpgProcess = new QProcess(this);
+ qDebug() << "gpgExec" << gpgExec << args;
+
+ gpgProcess->setReadChannel(QProcess::StandardOutput);
+ connect(gpgProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
+ gpgProcess, SLOT(deleteLater()));
+ connect(gpgProcess, &QProcess::readyReadStandardOutput, this, [gpgProcess, interactFunc]() {
+ qDebug() << "Function Called" << &gpgProcess;
+ // interactFunc(gpgProcess);
+ });
- qDebug() << args;
- QProcess gpg;
- // qDebug() << "engine->file_name" << engine->file_name;
+ gpgProcess->start(gpgExec, args);
- gpg.start(gpgBin, args);
- gpg.waitForFinished();
+ if (gpgProcess->waitForStarted()){
+ qDebug() << "Gpg Process Started Success";
+ } else {
+ qDebug() << "Gpg Process Started Failed";
+ }
- *stdOut = gpg.readAllStandardOutput();
- *stdErr = gpg.readAllStandardError();
- qDebug() << *stdOut;
+ return gpgProcess;
}
/***
@@ -734,26 +693,6 @@ namespace GpgME {
return gpgmeError;
}
- /***
- * return type should contain:
- * -> list of sigs
- * -> valid
- * -> decrypted message
- */
- //void GpgContext::decryptVerify(QByteArray in) {
-
- /* gpgme_error_t err;
- gpgme_data_t in, out;
-
- gpgme_decrypt_result_t decrypt_result;
- gpgme_verify_result_t verify_result;
-
- err = gpgme_op_decrypt_verify (mCtx, in, out);
- decrypt_result = gpgme_op_decrypt_result (mCtx);
-
- verify_result = gpgme_op_verify_result (mCtx);
- */
- //}
gpg_error_t
GpgContext::sign(const QVector<GpgKey> &keys, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached,
gpgme_sign_result_t *result) {
@@ -962,7 +901,7 @@ namespace GpgME {
void GpgContext::setSigners(const QVector<GpgKey> &keys) {
gpgme_signers_clear(mCtx);
for (const auto &key : keys) {
- if(checkIfKeyCanSign(key)) {
+ if (checkIfKeyCanSign(key)) {
auto gpgmeError = gpgme_signers_add(mCtx, key.key_refer);
checkErr(gpgmeError);
}
@@ -1180,7 +1119,7 @@ namespace GpgME {
}
}
- if(gpgme_err_code(err) != GPG_ERR_NO_ERROR)
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR)
checkErr(err);
if (dataIn) {
@@ -1240,11 +1179,11 @@ namespace GpgME {
return false;
}
- for (const auto& key : keys) {
+ for (const auto &key : keys) {
err = gpgme_data_new(&dataOut);
checkErr(err);
- err = gpgme_op_export(mCtx,key.id.toUtf8().constData(), 0, dataOut);
+ err = gpgme_op_export(mCtx, key.id.toUtf8().constData(), 0, dataOut);
checkErr(err);
read_bytes = gpgme_data_seek(dataOut, 0, SEEK_END);
@@ -1255,4 +1194,41 @@ namespace GpgME {
}
return true;
}
+
+ QProcess * GpgContext::generateRevokeCert(const GpgKey &key, const QString &outputFileName) {
+ QByteArray out, stdErr;
+ auto process = executeGpgCommand({
+ "--command-fd",
+ "0",
+ "--status-fd", "1",
+ "-o",
+ outputFileName,
+ "--gen-revoke",
+ key.fpr
+ }, &out, &stdErr,
+ [](QProcess *proc) {
+ qDebug() << "Function Called" << proc;
+ while (proc->canReadLine()) {
+ const QString line = QString::fromUtf8(proc->readLine()).trimmed();
+ // Command-fd is a stable interface, while this is all kind of hacky we
+ // are on a deadline :-/
+ if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) {
+ proc->write("y\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_LINE ask_revocation_reason.code")) {
+ proc->write("0\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_LINE ask_revocation_reason.text")) {
+ proc->write("\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_BOOL openfile.overwrite.okay")) {
+ // We asked before
+ proc->write("y\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_BOOL ask_revocation_reason.okay")) {
+ proc->write("y\n");
+ }
+ }
+ });
+
+ qDebug() << "GenerateRevokeCert Process" << process;
+
+ return process;
+ }
}
diff --git a/src/main.cpp b/src/main.cpp
index 00ab2738..ff3b0bb4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -23,6 +23,7 @@
*/
#include "MainWindow.h"
+#include "GpgFrontendBuildInfo.h"
int main(int argc, char *argv[]) {
@@ -61,7 +62,7 @@ int main(int argc, char *argv[]) {
QTranslator translator, translator2;
int return_from_event_loop_code;
- qDebug() << settings.fileName();
+ qDebug() << "Resource Directory" << RESOURCE_DIR(appPath);
do {
QApplication::removeTranslator(&translator);
diff --git a/src/smtp/CMakeLists.txt b/src/smtp/CMakeLists.txt
new file mode 100644
index 00000000..8e341f98
--- /dev/null
+++ b/src/smtp/CMakeLists.txt
@@ -0,0 +1,6 @@
+aux_source_directory(. SMTP_MIME_SOURCE)
+
+add_library(smtp STATIC ${SMTP_MIME_SOURCE})
+
+target_link_libraries(smtp
+ Qt5::Network Qt5::Core)
diff --git a/src/smtp/emailaddress.cpp b/src/smtp/emailaddress.cpp
new file mode 100644
index 00000000..c0ecaa0d
--- /dev/null
+++ b/src/smtp/emailaddress.cpp
@@ -0,0 +1,44 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/emailaddress.h"
+
+/* [1] Constructors and Destructors */
+
+EmailAddress::EmailAddress(const QString &address, const QString &name) {
+ this->address = address;
+ this->name = name;
+}
+
+EmailAddress::~EmailAddress() {}
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void EmailAddress::setName(const QString &name) { this->name = name; }
+
+void EmailAddress::setAddress(const QString &address) {
+ this->address = address;
+}
+
+const QString &EmailAddress::getName() const { return name; }
+
+const QString &EmailAddress::getAddress() const { return address; }
+
+/* [2] --- */
diff --git a/src/smtp/mimeattachment.cpp b/src/smtp/mimeattachment.cpp
new file mode 100644
index 00000000..033eecfb
--- /dev/null
+++ b/src/smtp/mimeattachment.cpp
@@ -0,0 +1,43 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimeattachment.h"
+#include <QFileInfo>
+
+/* [1] Constructors and Destructors */
+
+MimeAttachment::MimeAttachment(QFile *file) : MimeFile(file) {}
+
+MimeAttachment::MimeAttachment(const QByteArray &stream,
+ const QString &fileName)
+ : MimeFile(stream, fileName) {}
+
+MimeAttachment::~MimeAttachment() = default;
+
+/* [1] --- */
+
+/* [2] Protected methods */
+
+void MimeAttachment::prepare() {
+ this->header += "Content-disposition: attachment\r\n";
+
+ /* !!! IMPORTANT !!! */
+ MimeFile::prepare();
+}
+
+/* [2] --- */
diff --git a/src/smtp/mimecontentformatter.cpp b/src/smtp/mimecontentformatter.cpp
new file mode 100644
index 00000000..8f538457
--- /dev/null
+++ b/src/smtp/mimecontentformatter.cpp
@@ -0,0 +1,59 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimecontentformatter.h"
+
+MimeContentFormatter::MimeContentFormatter(int max_length)
+ : max_length(max_length) {}
+
+QString MimeContentFormatter::format(const QString &content,
+ bool quotedPrintable) const {
+
+ QString out;
+
+ int chars = 0;
+ for (auto i : content) {
+ chars++;
+ if (!quotedPrintable) {
+ if (chars > max_length) {
+ out.append("\r\n");
+ chars = 1;
+ }
+ } else {
+ if (i == '\n') { // new line
+ out.append(i);
+ chars = 0;
+ continue;
+ }
+
+ if ((chars > max_length - 1) ||
+ ((i == '=') && (chars > max_length - 3))) {
+ out.append('=');
+ out.append("\r\n");
+ chars = 1;
+ }
+ }
+ out.append(i);
+ }
+
+ return out;
+}
+
+void MimeContentFormatter::setMaxLength(int l) { max_length = l; }
+
+int MimeContentFormatter::getMaxLength() const { return max_length; }
diff --git a/src/smtp/mimefile.cpp b/src/smtp/mimefile.cpp
new file mode 100644
index 00000000..4f095b84
--- /dev/null
+++ b/src/smtp/mimefile.cpp
@@ -0,0 +1,61 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimefile.h"
+#include <QFileInfo>
+
+/* [1] Constructors and Destructors */
+
+MimeFile::MimeFile(QFile *file) {
+ this->file = file;
+ this->cType = "application/octet-stream";
+ this->cName = QFileInfo(*file).fileName();
+ this->cEncoding = Base64;
+}
+
+MimeFile::MimeFile(const QByteArray &stream, const QString &fileName) {
+ this->cEncoding = Base64;
+ this->cType = "application/octet-stream";
+ this->file = nullptr;
+ this->cName = fileName;
+ this->content = stream;
+}
+
+MimeFile::~MimeFile() {
+ delete file;
+}
+
+/* [1] --- */
+
+/* [2] Getters and setters */
+
+/* [2] --- */
+
+/* [3] Protected methods */
+
+void MimeFile::prepare() {
+ if (this->file) {
+ file->open(QIODevice::ReadOnly);
+ this->content = file->readAll();
+ file->close();
+ }
+ /* !!! IMPORTANT !!!! */
+ MimePart::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimehtml.cpp b/src/smtp/mimehtml.cpp
new file mode 100644
index 00000000..9f3a53c3
--- /dev/null
+++ b/src/smtp/mimehtml.cpp
@@ -0,0 +1,46 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimehtml.h"
+
+/* [1] Constructors and Destructors */
+
+MimeHtml::MimeHtml(const QString &html) : MimeText(html) {
+ this->cType = "text/html";
+}
+
+MimeHtml::~MimeHtml() = default;
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void MimeHtml::setHtml(const QString &html) { this->text = html; }
+
+const QString &MimeHtml::getHtml() const { return text; }
+
+/* [2] --- */
+
+/* [3] Protected methods */
+
+void MimeHtml::prepare() {
+ /* !!! IMPORTANT !!! */
+ MimeText::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimeinlinefile.cpp b/src/smtp/mimeinlinefile.cpp
new file mode 100644
index 00000000..a49167e8
--- /dev/null
+++ b/src/smtp/mimeinlinefile.cpp
@@ -0,0 +1,42 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimeinlinefile.h"
+
+/* [1] Constructors and Destructors */
+
+MimeInlineFile::MimeInlineFile(QFile *f) : MimeFile(f) {}
+
+MimeInlineFile::~MimeInlineFile() = default;
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+/* [2] --- */
+
+/* [3] Protected methods */
+
+void MimeInlineFile::prepare() {
+ this->header += "Content-Disposition: inline\r\n";
+
+ /* !!! IMPORTANT !!! */
+ MimeFile::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimemessage.cpp b/src/smtp/mimemessage.cpp
new file mode 100644
index 00000000..cf653e0a
--- /dev/null
+++ b/src/smtp/mimemessage.cpp
@@ -0,0 +1,308 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimemessage.h"
+#include "smtp/quotedprintable.h"
+
+#include <QDateTime>
+#include <QLocale>
+#include <typeinfo>
+
+/* [1] Constructors and Destructors */
+MimeMessage::MimeMessage(bool createAutoMimeContent)
+ : replyTo(nullptr), hEncoding(MimePart::_8Bit) {
+ if (createAutoMimeContent)
+ this->content = new MimeMultiPart();
+
+ autoMimeContentCreated = createAutoMimeContent;
+}
+
+MimeMessage::~MimeMessage() {
+ if (this->autoMimeContentCreated) {
+ this->autoMimeContentCreated = false;
+ delete (this->content);
+ }
+}
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+MimePart &MimeMessage::getContent() { return *content; }
+
+void MimeMessage::setContent(MimePart *content) {
+ if (this->autoMimeContentCreated) {
+ this->autoMimeContentCreated = false;
+ delete (this->content);
+ }
+ this->content = content;
+}
+
+void MimeMessage::setReplyTo(EmailAddress *rto) { replyTo = rto; }
+
+void MimeMessage::setSender(EmailAddress *e) {
+ this->sender = e;
+ e->setParent(this);
+}
+
+void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type) {
+ switch (type) {
+ case To:
+ recipientsTo << rcpt;
+ break;
+ case Cc:
+ recipientsCc << rcpt;
+ break;
+ case Bcc:
+ recipientsBcc << rcpt;
+ break;
+ }
+
+ rcpt->setParent(this);
+}
+
+void MimeMessage::addTo(EmailAddress *rcpt) { this->recipientsTo << rcpt; }
+
+void MimeMessage::addCc(EmailAddress *rcpt) { this->recipientsCc << rcpt; }
+
+void MimeMessage::addBcc(EmailAddress *rcpt) { this->recipientsBcc << rcpt; }
+
+void MimeMessage::setSubject(const QString &subject) {
+ this->subject = subject;
+}
+
+void MimeMessage::addPart(MimePart *part) {
+ if (typeid(*content) == typeid(MimeMultiPart)) {
+ ((MimeMultiPart *) content)->addPart(part);
+ };
+}
+
+void MimeMessage::setInReplyTo(const QString &inReplyTo) {
+ mInReplyTo = inReplyTo;
+}
+
+void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc) {
+ this->hEncoding = hEnc;
+}
+
+const EmailAddress &MimeMessage::getSender() const { return *sender; }
+
+const QList<EmailAddress *> &
+MimeMessage::getRecipients(RecipientType type) const {
+ switch (type) {
+ default:
+ case To:
+ return recipientsTo;
+ case Cc:
+ return recipientsCc;
+ case Bcc:
+ return recipientsBcc;
+ }
+}
+
+const EmailAddress *MimeMessage::getReplyTo() const { return replyTo; }
+
+const QString &MimeMessage::getSubject() const { return subject; }
+
+const QList<MimePart *> &MimeMessage::getParts() const {
+ if (typeid(*content) == typeid(MimeMultiPart)) {
+ return ((MimeMultiPart *) content)->getParts();
+ } else {
+ auto *res = new QList<MimePart *>();
+ res->append(content);
+ return *res;
+ }
+}
+
+/* [2] --- */
+
+/* [3] Public Methods */
+
+QString MimeMessage::toString() {
+ QString mime;
+
+ /* =========== MIME HEADER ============ */
+
+ /* ---------- Sender / From ----------- */
+ mime = "From:";
+ if (sender->getName() != "") {
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += " =?utf-8?B?" +
+ QByteArray().append(sender->getName().toUtf8()).toBase64() + "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(
+ QByteArray().append(sender->getName().toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += " " + sender->getName();
+ }
+ }
+ mime += " <" + sender->getAddress() + ">\r\n";
+ /* ---------------------------------- */
+
+ /* ------- Recipients / To ---------- */
+ mime += "To:";
+ QList<EmailAddress *>::iterator it;
+ int i;
+ for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i) {
+ if (i != 0) {
+ mime += ",";
+ }
+
+ if ((*it)->getName() != "") {
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += " =?utf-8?B?" +
+ QByteArray().append((*it)->getName().toUtf8()).toBase64() +
+ "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(
+ QByteArray().append((*it)->getName().toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += " " + (*it)->getName();
+ }
+ }
+ mime += " <" + (*it)->getAddress() + ">";
+ }
+ mime += "\r\n";
+ /* ---------------------------------- */
+
+ /* ------- Recipients / Cc ---------- */
+ if (!recipientsCc.empty()) {
+ mime += "Cc:";
+ }
+ for (i = 0, it = recipientsCc.begin(); it != recipientsCc.end(); ++it, ++i) {
+ if (i != 0) {
+ mime += ",";
+ }
+
+ if ((*it)->getName() != "") {
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += " =?utf-8?B?" +
+ QByteArray().append((*it)->getName().toUtf8()).toBase64() +
+ "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(
+ QByteArray().append((*it)->getName().toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += " " + (*it)->getName();
+ }
+ }
+ mime += " <" + (*it)->getAddress() + ">";
+ }
+ if (!recipientsCc.empty()) {
+ mime += "\r\n";
+ }
+ /* ---------------------------------- */
+
+ /* ------------ Subject ------------- */
+ mime += "Subject: ";
+
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += "=?utf-8?B?" + QByteArray().append(subject.toUtf8()).toBase64() + "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += "=?utf-8?Q?" +
+ QuotedPrintable::encode(QByteArray().append(subject.toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += subject;
+ }
+ mime += "\r\n";
+ /* ---------------------------------- */
+
+ /* ---------- Reply-To -------------- */
+ if (replyTo) {
+ mime += "Reply-To: ";
+ if (replyTo->getName() != "") {
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += " =?utf-8?B?" +
+ QByteArray().append(replyTo->getName().toUtf8()).toBase64() + "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(QByteArray().append(replyTo->getName().toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += " " + replyTo->getName();
+ }
+ }
+ mime += " <" + replyTo->getAddress() + ">\r\n";
+ }
+
+ /* ---------------------------------- */
+
+ mime += "MIME-Version: 1.0\r\n";
+ if (!mInReplyTo.isEmpty()) {
+ mime += "In-Reply-To: <" + mInReplyTo + ">\r\n";
+ mime += "References: <" + mInReplyTo + ">\r\n";
+ }
+
+ QDateTime now = QDateTime::currentDateTime();
+#if QT_VERSION_MAJOR < 5 // Qt4 workaround since RFC2822Date isn't defined
+ QString shortDayName =
+ QLocale::c().dayName(now.date().dayOfWeek(), QLocale::ShortFormat);
+ QString shortMonthName =
+ QLocale::c().monthName(now.date().month(), QLocale::ShortFormat);
+ int utcOffset = now.secsTo(QDateTime(now.date(), now.time(), Qt::UTC)) / 60;
+ char timezoneSign = utcOffset >= 0 ? '+' : '-';
+ utcOffset = utcOffset >= 0 ? utcOffset : -utcOffset;
+ QString timezone = QString("%1%2%3")
+ .arg(timezoneSign)
+ .arg(utcOffset / 60, 2, 10, QChar('0'))
+ .arg(utcOffset % 60, 2, 10, QChar('0'));
+ mime += QString("Date: %1\r\n")
+ .arg(now.toString("%1, dd %2 yyyy hh:mm:ss %3")
+ .arg(shortDayName)
+ .arg(shortMonthName)
+ .arg(timezone));
+#else // Qt5 supported
+ mime += QString("Date: %1\r\n").arg(now.toString(Qt::RFC2822Date));
+#endif // support RFC2822Date
+
+ mime += content->toString();
+ return mime;
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimemultipart.cpp b/src/smtp/mimemultipart.cpp
new file mode 100644
index 00000000..14a813c2
--- /dev/null
+++ b/src/smtp/mimemultipart.cpp
@@ -0,0 +1,70 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimemultipart.h"
+#include <QCryptographicHash>
+#include <QRandomGenerator>
+#include <QTime>
+
+const QString MULTI_PART_NAMES[] = {
+ "multipart/mixed", // Mixed
+ "multipart/digest", // Digest
+ "multipart/alternative", // Alternative
+ "multipart/related", // Related
+ "multipart/report", // Report
+ "multipart/signed", // Signed
+ "multipart/encrypted" // Encrypted
+};
+
+MimeMultiPart::MimeMultiPart(MultiPartType type) {
+ this->type = type;
+ this->cType = MULTI_PART_NAMES[this->type];
+ this->cEncoding = _8Bit;
+
+ QRandomGenerator generator;
+
+ QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(QByteArray().append((char) generator.generate()));
+ cBoundary = md5.result().toHex();
+}
+
+void MimeMultiPart::addPart(MimePart *part) { parts.append(part); }
+
+const QList<MimePart *> &MimeMultiPart::getParts() const { return parts; }
+
+void MimeMultiPart::prepare() {
+ QList<MimePart *>::iterator it;
+
+ content = "";
+ for (it = parts.begin(); it != parts.end(); it++) {
+ content += QString("--" + cBoundary + "\r\n").toUtf8();
+ (*it)->prepare();
+ content += (*it)->toString().toUtf8();
+ };
+
+ content += QString("--" + cBoundary + "--\r\n").toUtf8();
+
+ MimePart::prepare();
+}
+
+void MimeMultiPart::setMimeType(const MultiPartType type) {
+ this->type = type;
+ this->cType = MULTI_PART_NAMES[type];
+}
+
+MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const { return type; }
diff --git a/src/smtp/mimepart.cpp b/src/smtp/mimepart.cpp
new file mode 100644
index 00000000..5d33884d
--- /dev/null
+++ b/src/smtp/mimepart.cpp
@@ -0,0 +1,159 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimepart.h"
+#include "smtp/quotedprintable.h"
+
+/* [1] Constructors and Destructors */
+
+MimePart::MimePart() {
+ cEncoding = _7Bit;
+ prepared = false;
+ cBoundary = "";
+}
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void MimePart::setContent(const QByteArray &content) {
+ this->content = content;
+}
+
+void MimePart::setHeader(const QString &header) { this->header = header; }
+
+void MimePart::addHeaderLine(const QString &line) {
+ this->header += line + "\r\n";
+}
+
+const QString &MimePart::getHeader() const { return header; }
+
+const QByteArray &MimePart::getContent() const { return content; }
+
+void MimePart::setContentId(const QString &cId) { this->cId = cId; }
+
+const QString &MimePart::getContentId() const { return this->cId; }
+
+void MimePart::setContentName(const QString &cName) { this->cName = cName; }
+
+const QString &MimePart::getContentName() const { return this->cName; }
+
+void MimePart::setContentType(const QString &cType) { this->cType = cType; }
+
+const QString &MimePart::getContentType() const { return this->cType; }
+
+void MimePart::setCharset(const QString &charset) { this->cCharset = charset; }
+
+const QString &MimePart::getCharset() const { return this->cCharset; }
+
+void MimePart::setEncoding(Encoding enc) { this->cEncoding = enc; }
+
+MimePart::Encoding MimePart::getEncoding() const { return this->cEncoding; }
+
+MimeContentFormatter &MimePart::getContentFormatter() {
+ return this->formatter;
+}
+
+/* [2] --- */
+
+/* [3] Public methods */
+
+QString MimePart::toString() {
+ if (!prepared)
+ prepare();
+
+ return mimeString;
+}
+
+/* [3] --- */
+
+/* [4] Protected methods */
+
+void MimePart::prepare() {
+ mimeString = QString();
+
+ /* === Header Prepare === */
+
+ /* Content-Type */
+ mimeString.append("Content-Type: ").append(cType);
+
+ if (cName != "")
+ mimeString.append("; name=\"").append(cName).append("\"");
+
+ if (cCharset != "")
+ mimeString.append("; charset=").append(cCharset);
+
+ if (cBoundary != "")
+ mimeString.append("; boundary=").append(cBoundary);
+
+ mimeString.append("\r\n");
+ /* ------------ */
+
+ /* Content-Transfer-Encoding */
+ mimeString.append("Content-Transfer-Encoding: ");
+ switch (cEncoding) {
+ case _7Bit:
+ mimeString.append("7bit\r\n");
+ break;
+ case _8Bit:
+ mimeString.append("8bit\r\n");
+ break;
+ case Base64:
+ mimeString.append("base64\r\n");
+ break;
+ case QuotedPrintable:
+ mimeString.append("quoted-printable\r\n");
+ break;
+ }
+ /* ------------------------ */
+
+ /* Content-Id */
+ if (cId != NULL)
+ mimeString.append("Content-ID: <").append(cId).append(">\r\n");
+ /* ---------- */
+
+ /* Addition header lines */
+
+ mimeString.append(header).append("\r\n");
+
+ /* ------------------------- */
+
+ /* === End of Header Prepare === */
+
+ /* === Content === */
+ switch (cEncoding) {
+ case _7Bit:
+ mimeString.append(QString(content).toLatin1());
+ break;
+ case _8Bit:
+ mimeString.append(content);
+ break;
+ case Base64:
+ mimeString.append(formatter.format(content.toBase64()));
+ break;
+ case QuotedPrintable:
+ mimeString.append(formatter.format(QuotedPrintable::encode(content), true));
+ break;
+ }
+ mimeString.append("\r\n");
+ /* === End of Content === */
+
+ prepared = true;
+}
+
+/* [4] --- */
diff --git a/src/smtp/mimetext.cpp b/src/smtp/mimetext.cpp
new file mode 100644
index 00000000..3726647e
--- /dev/null
+++ b/src/smtp/mimetext.cpp
@@ -0,0 +1,52 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimetext.h"
+
+/* [1] Constructors and Destructors */
+
+MimeText::MimeText(const QString &txt) {
+ this->text = txt;
+ this->cType = "text/plain";
+ this->cCharset = "utf-8";
+ this->cEncoding = _8Bit;
+}
+
+MimeText::~MimeText() = default;
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void MimeText::setText(const QString &text) { this->text = text; }
+
+const QString &MimeText::getText() const { return text; }
+
+/* [2] --- */
+
+/* [3] Protected Methods */
+
+void MimeText::prepare() {
+ this->content.clear();
+ this->content.append(text.toUtf8());
+
+ /* !!! IMPORTANT !!! */
+ MimePart::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/quotedprintable.cpp b/src/smtp/quotedprintable.cpp
new file mode 100644
index 00000000..93e51122
--- /dev/null
+++ b/src/smtp/quotedprintable.cpp
@@ -0,0 +1,62 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/quotedprintable.h"
+
+QString QuotedPrintable::encode(const QByteArray &input) {
+ QString output;
+
+ char byte;
+ const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ for (char i : input) {
+ byte = i;
+
+ if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61))) {
+ output.append(byte);
+ } else {
+ output.append('=');
+ output.append(hex[((byte >> 4) & 0x0F)]);
+ output.append(hex[(byte & 0x0F)]);
+ }
+ }
+
+ return output;
+}
+
+QByteArray QuotedPrintable::decode(const QString &input) {
+ // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B
+ // C D E F
+ const int hexVal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0,
+ 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
+
+ QByteArray output;
+
+ for (int i = 0; i < input.length(); ++i) {
+ if (input.at(i).toLatin1() == '=') {
+ output.append((hexVal[input.at(i + 1).toLatin1() - '0'] << 4) +
+ hexVal[input.at(i + 2).toLatin1() - '0']);
+ i += 2;
+ } else {
+ output.append(input.at(i).toLatin1());
+ }
+ }
+
+ return output;
+}
diff --git a/src/smtp/smtpclient.cpp b/src/smtp/smtpclient.cpp
new file mode 100644
index 00000000..63202998
--- /dev/null
+++ b/src/smtp/smtpclient.cpp
@@ -0,0 +1,407 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/smtpclient.h"
+
+#include <QByteArray>
+#include <QFileInfo>
+
+/* [1] Constructors and destructors */
+
+SmtpClient::SmtpClient(const QString &host, int port,
+ ConnectionType connectionType)
+ : socket(NULL), name("localhost"), authMethod(AuthPlain),
+ connectionTimeout(5000), responseTimeout(5000),
+ sendMessageTimeout(60000) {
+ setConnectionType(connectionType);
+
+ this->host = host;
+ this->port = port;
+
+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this,
+ SLOT(socketStateChanged(QAbstractSocket::SocketState)));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
+ SLOT(socketError(QAbstractSocket::SocketError)));
+ connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
+}
+
+SmtpClient::~SmtpClient() {
+ if (socket)
+ delete socket;
+}
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void SmtpClient::setUser(const QString &user) { this->user = user; }
+
+void SmtpClient::setPassword(const QString &password) {
+ this->password = password;
+}
+
+void SmtpClient::setAuthMethod(AuthMethod method) { this->authMethod = method; }
+
+void SmtpClient::setHost(const QString &host) { this->host = host; }
+
+void SmtpClient::setPort(int port) { this->port = port; }
+
+void SmtpClient::setConnectionType(ConnectionType ct) {
+ this->connectionType = ct;
+
+ if (socket)
+ delete socket;
+
+ switch (connectionType) {
+ case TcpConnection:
+ socket = new QTcpSocket(this);
+ break;
+ case SslConnection:
+ case TlsConnection:
+ socket = new QSslSocket(this);
+ }
+}
+
+const QString &SmtpClient::getHost() const { return this->host; }
+
+const QString &SmtpClient::getUser() const { return this->user; }
+
+const QString &SmtpClient::getPassword() const { return this->password; }
+
+SmtpClient::AuthMethod SmtpClient::getAuthMethod() const {
+ return this->authMethod;
+}
+
+int SmtpClient::getPort() const { return this->port; }
+
+SmtpClient::ConnectionType SmtpClient::getConnectionType() const {
+ return connectionType;
+}
+
+const QString &SmtpClient::getName() const { return this->name; }
+
+void SmtpClient::setName(const QString &name) { this->name = name; }
+
+const QString &SmtpClient::getResponseText() const { return responseText; }
+
+int SmtpClient::getResponseCode() const { return responseCode; }
+
+QTcpSocket *SmtpClient::getSocket() { return socket; }
+
+int SmtpClient::getConnectionTimeout() const { return connectionTimeout; }
+
+void SmtpClient::setConnectionTimeout(int msec) { connectionTimeout = msec; }
+
+int SmtpClient::getResponseTimeout() const { return responseTimeout; }
+
+void SmtpClient::setResponseTimeout(int msec) { responseTimeout = msec; }
+
+int SmtpClient::getSendMessageTimeout() const { return sendMessageTimeout; }
+
+void SmtpClient::setSendMessageTimeout(int msec) { sendMessageTimeout = msec; }
+
+/* [2] --- */
+
+/* [3] Public methods */
+
+bool SmtpClient::connectToHost() {
+ switch (connectionType) {
+ case TlsConnection:
+ case TcpConnection:
+ socket->connectToHost(host, port);
+ break;
+ case SslConnection:
+ ((QSslSocket *) socket)->connectToHostEncrypted(host, port);
+ break;
+ }
+
+ // Tries to connect to server
+ if (!socket->waitForConnected(connectionTimeout)) {
+ emit smtpError(ConnectionTimeoutError);
+ return false;
+ }
+
+ try {
+ // Wait for the server's response
+ waitForResponse();
+
+ // If the response code is not 220 (Service ready)
+ // means that is something wrong with the server
+ if (responseCode != 220) {
+ emit smtpError(ServerError);
+ return false;
+ }
+
+ // Send a EHLO/HELO message to the server
+ // The client's first command must be EHLO/HELO
+ sendMessage("EHLO " + name);
+
+ // Wait for the server's response
+ waitForResponse();
+
+ // The response code needs to be 250.
+ if (responseCode != 250) {
+ emit smtpError(ServerError);
+ return false;
+ }
+
+ if (connectionType == TlsConnection) {
+ // send a request to start TLS handshake
+ sendMessage("STARTTLS");
+
+ // Wait for the server's response
+ waitForResponse();
+
+ // The response code needs to be 220.
+ if (responseCode != 220) {
+ emit smtpError(ServerError);
+ return false;
+ };
+
+ ((QSslSocket *) socket)->startClientEncryption();
+
+ if (!((QSslSocket *) socket)->waitForEncrypted(connectionTimeout)) {
+ qDebug() << ((QSslSocket *) socket)->errorString();
+ emit smtpError(ConnectionTimeoutError);
+ return false;
+ }
+
+ // Send ELHO one more time
+ sendMessage("EHLO " + name);
+
+ // Wait for the server's response
+ waitForResponse();
+
+ // The response code needs to be 250.
+ if (responseCode != 250) {
+ emit smtpError(ServerError);
+ return false;
+ }
+ }
+ } catch (ResponseTimeoutException) {
+ return false;
+ } catch (SendMessageTimeoutException) {
+ return false;
+ }
+
+ // If no errors occured the function returns true.
+ return true;
+}
+
+bool SmtpClient::login() { return login(user, password, authMethod); }
+
+bool SmtpClient::login(const QString &user, const QString &password,
+ AuthMethod method) {
+ try {
+ if (method == AuthPlain) {
+ // Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
+ sendMessage("AUTH PLAIN " + QByteArray()
+ .append((char) 0)
+ .append(user.toUtf8())
+ .append((char) 0)
+ .append(password.toUtf8())
+ .toBase64());
+
+ // Wait for the server's response
+ waitForResponse();
+
+ // If the response is not 235 then the authentication was faild
+ if (responseCode != 235) {
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+ } else if (method == AuthLogin) {
+ // Sending command: AUTH LOGIN
+ sendMessage("AUTH LOGIN");
+
+ // Wait for 334 response code
+ waitForResponse();
+ if (responseCode != 334) {
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+
+ // Send the username in base64
+ sendMessage(QByteArray().append(user.toUtf8()).toBase64());
+
+ // Wait for 334
+ waitForResponse();
+ if (responseCode != 334) {
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+
+ // Send the password in base64
+ sendMessage(QByteArray().append(password.toUtf8()).toBase64());
+
+ // Wait for the server's responce
+ waitForResponse();
+
+ // If the response is not 235 then the authentication was faild
+ if (responseCode != 235) {
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+ }
+ } catch (ResponseTimeoutException) {
+ // Responce Timeout exceeded
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ } catch (SendMessageTimeoutException) {
+ // Send Timeout exceeded
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+
+ return true;
+}
+
+bool SmtpClient::sendMail(MimeMessage &email) {
+ try {
+ // Send the MAIL command with the sender
+ sendMessage("MAIL FROM:<" + email.getSender().getAddress() + ">");
+
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+
+ // Send RCPT command for each recipient
+ QList<EmailAddress *>::const_iterator it, itEnd;
+ // To (primary recipients)
+ for (it = email.getRecipients().begin(),
+ itEnd = email.getRecipients().end();
+ it != itEnd; ++it) {
+
+ sendMessage("RCPT TO:<" + (*it)->getAddress() + ">");
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+ }
+
+ // Cc (carbon copy)
+ for (it = email.getRecipients(MimeMessage::Cc).begin(),
+ itEnd = email.getRecipients(MimeMessage::Cc).end();
+ it != itEnd; ++it) {
+ sendMessage("RCPT TO:<" + (*it)->getAddress() + ">");
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+ }
+
+ // Bcc (blind carbon copy)
+ for (it = email.getRecipients(MimeMessage::Bcc).begin(),
+ itEnd = email.getRecipients(MimeMessage::Bcc).end();
+ it != itEnd; ++it) {
+ sendMessage("RCPT TO:<" + (*it)->getAddress() + ">");
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+ }
+
+ // Send DATA command
+ sendMessage("DATA");
+ waitForResponse();
+
+ if (responseCode != 354)
+ return false;
+
+ sendMessage(email.toString());
+
+ // Send \r\n.\r\n to end the mail data
+ sendMessage(".");
+
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+ } catch (ResponseTimeoutException) {
+ return false;
+ } catch (SendMessageTimeoutException) {
+ return false;
+ }
+
+ return true;
+}
+
+void SmtpClient::quit() {
+ try {
+ sendMessage("QUIT");
+ } catch (SmtpClient::SendMessageTimeoutException) {
+ // Manually close the connection to the smtp server if message "QUIT" wasn't
+ // received by the smtp server
+ if (socket->state() == QAbstractSocket::ConnectedState ||
+ socket->state() == QAbstractSocket::ConnectingState ||
+ socket->state() == QAbstractSocket::HostLookupState)
+ socket->disconnectFromHost();
+ }
+}
+
+/* [3] --- */
+
+/* [4] Protected methods */
+
+void SmtpClient::waitForResponse() {
+ do {
+ if (!socket->waitForReadyRead(responseTimeout)) {
+ emit smtpError(ResponseTimeoutError);
+ throw ResponseTimeoutException();
+ }
+
+ while (socket->canReadLine()) {
+ // Save the server's response
+ responseText = socket->readLine();
+
+ // Extract the respose code from the server's responce (first 3 digits)
+ responseCode = responseText.leftRef(3).toInt();
+
+ if (responseCode / 100 == 4)
+ emit smtpError(ServerError);
+
+ if (responseCode / 100 == 5)
+ emit smtpError(ClientError);
+
+ if (responseText[3] == ' ') {
+ return;
+ }
+ }
+ } while (true);
+}
+
+void SmtpClient::sendMessage(const QString &text) {
+ socket->write(text.toUtf8() + "\r\n");
+ if (!socket->waitForBytesWritten(sendMessageTimeout)) {
+ emit smtpError(SendDataTimeoutError);
+ throw SendMessageTimeoutException();
+ }
+}
+
+/* [4] --- */
+
+/* [5] Slots for the socket's signals */
+
+void SmtpClient::socketStateChanged(QAbstractSocket::SocketState /*state*/) {}
+
+void SmtpClient::socketError(QAbstractSocket::SocketError /*socketError*/) {}
+
+void SmtpClient::socketReadyRead() {}
+
+/* [5] --- */
diff --git a/src/ui/AboutDialog.cpp b/src/ui/AboutDialog.cpp
deleted file mode 100644
index e51f225d..00000000
--- a/src/ui/AboutDialog.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-#include "ui/AboutDialog.h"
-
-AboutDialog::AboutDialog(QWidget *parent)
- : QDialog(parent) {
- this->setWindowTitle(tr("About ") + qApp->applicationName());
-
- auto *tabWidget = new QTabWidget;
- auto *infoTab = new InfoTab;
- auto *translatorsTab = new TranslatorsTab;
-
- tabWidget->addTab(infoTab, tr("General"));
- tabWidget->addTab(translatorsTab, tr("Translators"));
-
- auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
- connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(tabWidget);
- mainLayout->addWidget(buttonBox);
- setLayout(mainLayout);
-
- this->exec();
-}
-
-InfoTab::InfoTab(QWidget *parent)
- : QWidget(parent) {
- auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
- auto *text = new QString("<center><h2>" + qApp->applicationName() + "</h2></center>"
- + "<center><b>" + qApp->applicationVersion() + "</b></center>"
- + "<center>" + GIT_VERSION + "</center>"
- + tr("<br><center>GPGFrontend is an easy-to-use, compact, <br>"
- "cross-platform, and installation-free gpg front-end tool.<br>"
- "It visualizes most of the common operations of gpg commands.<br>"
- "It's licensed under the GPL v3<br><br>"
- "<b>Developer:</b><br>"
- "Saturneric<br><br>"
- "If you have any questions or suggestions, raise an issue<br/>"
- "at <a href=\"https://github.com/saturneric/GpgFrontend\">GitHub</a> or send a mail to my mailing list at <a href=\"mailto:[email protected]\">[email protected]</a>.") +
- tr("<br><br> Built with Qt ") + qVersion()
- + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() +
- tr("<br>Built at ") + BUILD_TIMESTAMP + "</center>");
-
- auto *layout = new QGridLayout();
- auto *pixmapLabel = new QLabel();
- pixmapLabel->setPixmap(*pixmap);
- layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
- auto *aboutLabel = new QLabel();
- aboutLabel->setText(*text);
- aboutLabel->setOpenExternalLinks(true);
- layout->addWidget(aboutLabel, 1, 0, 1, -1);
- layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
- QSizePolicy::Fixed), 2, 1, 1, 1);
-
- setLayout(layout);
-}
-
-TranslatorsTab::TranslatorsTab(QWidget *parent)
- : QWidget(parent) {
- QFile translatorsFile;
- translatorsFile.setFileName(qApp->applicationDirPath() + "/About");
- translatorsFile.open(QIODevice::ReadOnly);
- QByteArray inBuffer = translatorsFile.readAll();
-
- auto *label = new QLabel(inBuffer);
- auto *mainLayout = new QVBoxLayout(this);
- mainLayout->addWidget(label);
-
- setLayout(mainLayout);
-}
-
diff --git a/src/ui/AttachmentTableModel.cpp b/src/ui/AttachmentTableModel.cpp
deleted file mode 100644
index 79cbdf9b..00000000
--- a/src/ui/AttachmentTableModel.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-#include "ui/AttachmentTableModel.h"
-
-#include <utility>
-
-/** compare with http://doc.qt.nokia.com/4.6/itemviews-addressbook.html
- */
-
-AttachmentTableModel::AttachmentTableModel(QObject *parent) :
- QAbstractTableModel(parent) {
-}
-
-AttachmentTableModel::AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent) :
- QAbstractTableModel(parent) {
- listOfMimeparts = std::move(mimeparts);
-}
-
-
-void AttachmentTableModel::add(const MimePart &mp) {
- listOfMimeparts.append(mp);
- //QModelIndex changedIndex0 = createIndex(listOfMimeparts.size(), 0);
- //QModelIndex changedIndex1 = createIndex(listOfMimeparts.size(), 1);
-
- //emit(dataChanged(changedIndex0, changedIndex1));
- // TODO: check the data-changed signal
- // reset();
-}
-
-MimePart AttachmentTableModel::getSelectedMimePart(QModelIndex index) {
- return listOfMimeparts.at(index.row());
-}
-
-MimePart AttachmentTableModel::getMimePart(int index) {
- return listOfMimeparts.at(index);
-}
-
-/*QList<MimePart> AttachmentTableModel::getSelectedMimeParts(QModelIndexList indexes){
-
- foreach(QModelIndex index, indexes) {
- qDebug() << "ir: "<< index.row();
- }
-
-}*/
-
-int AttachmentTableModel::rowCount(const QModelIndex &parent) const {
- Q_UNUSED(parent);
- return listOfMimeparts.size();
-}
-
-int AttachmentTableModel::columnCount(const QModelIndex &parent) const {
- Q_UNUSED(parent);
- return 2;
-}
-
-QVariant AttachmentTableModel::data(const QModelIndex &index, int role) const {
-
- //qDebug() << "called, index: " << index.column();
-
- if (!index.isValid())
- return QVariant();
-
- if (index.row() >= listOfMimeparts.size() || index.row() < 0)
- return QVariant();
-
- if (role == Qt::DisplayRole) {
- MimePart mp = listOfMimeparts.at(index.row());
-
- if (index.column() == 0)
- return mp.header.getParam("Content-Type", "name");
- if (index.column() == 1)
- return mp.header.getValue("Content-Type");
-
- }
-
- // set icon
- // TODO more generic matching, e.g. for audio
- if (role == Qt::DecorationRole && index.column() == 0) {
- MimePart mp = listOfMimeparts.at(index.row());
- QString icon;
- if (mp.header.getValue("Content-Type").startsWith("image")) {
- icon = ":mimetypes/image-x-generic.png";
- } else {
- icon = mp.header.getValue("Content-Type").replace("/", "-");
- icon = ":mimetypes/" + icon + ".png";
- }
- if (!QFile::exists(icon)) icon = ":mimetypes/unknown.png";
- return QIcon(icon);
- }
-
- return QVariant();
-}
-
-QVariant AttachmentTableModel::headerData(int section, Qt::Orientation orientation, int role) const {
- //qDebug() << "called, section: " << section;
- if (role != Qt::DisplayRole)
- return QVariant();
-
- if (orientation == Qt::Horizontal) {
- switch (section) {
- case 0:
- return tr("Filename");
-
- case 1:
- return tr("Contenttype");
-
- default:
- return QVariant();
- }
- }
- return QVariant();
-}
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 68f57b81..618b5d28 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -3,6 +3,7 @@ aux_source_directory(./keypair_details UI_SOURCE)
aux_source_directory(./widgets UI_SOURCE)
aux_source_directory(./keygen UI_SOURCE)
aux_source_directory(./main_window UI_SOURCE)
+aux_source_directory(./help UI_SOURCE)
add_library(gpgfrontend-ui STATIC ${UI_SOURCE})
diff --git a/src/ui/FileEncryptionDialog.cpp b/src/ui/FileEncryptionDialog.cpp
index 9cb7b00a..e92dfc90 100755
--- a/src/ui/FileEncryptionDialog.cpp
+++ b/src/ui/FileEncryptionDialog.cpp
@@ -203,27 +203,50 @@ void FileEncryptionDialog::slotExecuteAction() {
QVector<GpgKey> keys;
mKeyList->getCheckedKeys(keys);
+ qDebug() << "slotExecuteAction" << mAction;
+
if (mAction == Encrypt) {
- if (!mCtx->encrypt(keys, inBuffer, outBuffer, nullptr)) return;
+ qDebug() << "Action Encrypt";
+ gpgme_error_t err = mCtx->encrypt(keys, inBuffer, outBuffer, nullptr);
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
+ qDebug() << "Error" << gpgme_strerror(err);
+ QMessageBox::warning(this, tr("Error"),
+ tr("Error Occurred During Encryption"));
+ return;
+ }
}
if (mAction == Decrypt) {
- if (!mCtx->decrypt(inBuffer, outBuffer, nullptr)) return;
+ qDebug() << "Action Decrypt";
+ gpgme_error_t err = mCtx->decrypt(inBuffer, outBuffer, nullptr);
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
+ qDebug() << "Error" << gpgme_strerror(err);
+ QMessageBox::warning(this, tr("Error"),
+ tr("Error Occurred During Decryption"));
+ return;
+ }
}
if (mAction == Sign) {
- if (gpgme_err_code(mCtx->sign(keys, inBuffer, outBuffer, true)) != GPG_ERR_NO_ERROR) return;
+ qDebug() << "Action Sign";
+ gpgme_error_t err = mCtx->sign(keys, inBuffer, outBuffer, true);
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
+ qDebug() << "Error" << gpgme_strerror(err);
+ QMessageBox::warning(this, tr("Error"),
+ tr("Error Occurred During Signature"));
+ return;
+ }
}
if (mAction == Verify) {
- QFile signfile;
- signfile.setFileName(signFileEdit->text());
- if (!signfile.open(QIODevice::ReadOnly)) {
+ QFile sign_file;
+ sign_file.setFileName(signFileEdit->text());
+ if (!sign_file.open(QIODevice::ReadOnly)) {
statusLabel->setText(tr("Couldn't open file"));
signFileEdit->setStyleSheet("QLineEdit { background: yellow }");
return;
}
- auto signBuffer = signfile.readAll();
+ auto signBuffer = sign_file.readAll();
gpgme_verify_result_t result;
auto error = mCtx->verify(&inBuffer, &signBuffer, &result);
new VerifyDetailsDialog(this, mCtx, mKeyList, error, result);
diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp
index 0e2d9c9a..ce5343bf 100755
--- a/src/ui/KeyMgmt.cpp
+++ b/src/ui/KeyMgmt.cpp
@@ -78,7 +78,7 @@ KeyMgmt::KeyMgmt(GpgME::GpgContext *ctx, QWidget *parent ) :
this->settings.setValue("keymgmt/setWindowSize", true);
}
- setWindowTitle(tr("KeyPairs Management"));
+ setWindowTitle(tr("Key Pair Management"));
mKeyList->addMenuAction(deleteSelectedKeysAct);
mKeyList->addMenuAction(showKeyDetailsAct);
}
diff --git a/src/ui/KeyServerImportDialog.cpp b/src/ui/KeyServerImportDialog.cpp
index ec740691..a1355120 100644
--- a/src/ui/KeyServerImportDialog.cpp
+++ b/src/ui/KeyServerImportDialog.cpp
@@ -176,7 +176,7 @@ void KeyServerImportDialog::setMessage(const QString &text, bool error) {
void KeyServerImportDialog::slotSearch() {
if (searchLineEdit->text().isEmpty()) {
- setMessage(tr("<h4>Text is empty.</h4>"), false);
+ setMessage("<h4>" + tr("Text is empty.") + "</h4>", false);
return;
}
@@ -227,23 +227,23 @@ void KeyServerImportDialog::slotSearchFinished() {
if (firstLine.contains("Error")) {
QString text = QString(reply->readLine(1024));
if (text.contains("Too many responses")) {
- setMessage(tr("<h4>CToo many responses from keyserver!</h4>"), true);
+ setMessage("<h4>" +tr("Too many responses from keyserver!") + "</h4>", true);
return;
} else if (text.contains("No keys found")) {
// if string looks like hex string, search again with 0x prepended
QRegExp rx("[0-9A-Fa-f]*");
QString query = searchLineEdit->text();
if (rx.exactMatch(query)) {
- setMessage(tr("<h4>No keys found, input may be kexId, retrying search with 0x.</h4>"), true);
+ setMessage("<h4>" + tr("No keys found, input may be kexId, retrying search with 0x.") + "</h4>", true);
searchLineEdit->setText(query.prepend("0x"));
this->slotSearch();
return;
} else {
- setMessage(tr("<h4>No keys found containing the search string!</h4>"), true);
+ setMessage("<h4>" +tr("No keys found containing the search string!") + "</h4>", true);
return;
}
} else if (text.contains("Insufficiently specific words")) {
- setMessage(tr("<h4>Insufficiently specific search string!</h4>"), true);
+ setMessage("<h4>" + tr("Insufficiently specific search string!") + "</h4>", true);
return;
} else {
setMessage(text, true);
diff --git a/src/ui/KeyUploadDialog.cpp b/src/ui/KeyUploadDialog.cpp
index e28b4230..faf892f0 100644
--- a/src/ui/KeyUploadDialog.cpp
+++ b/src/ui/KeyUploadDialog.cpp
@@ -36,9 +36,13 @@ KeyUploadDialog::KeyUploadDialog(GpgME::GpgContext *ctx, const QVector<GpgKey> &
auto *pb = new QProgressBar();
pb->setRange(0, 0);
+ pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ pb->setTextVisible(false);
auto *layout = new QVBoxLayout();
layout->addWidget(pb);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
this->setLayout(layout);
this->setModal(true);
diff --git a/src/ui/SendMailDialog.cpp b/src/ui/SendMailDialog.cpp
new file mode 100644
index 00000000..5bea7cb2
--- /dev/null
+++ b/src/ui/SendMailDialog.cpp
@@ -0,0 +1,173 @@
+/**
+ * This file is part of GPGFrontend.
+ *
+ * GPGFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#include "ui/SendMailDialog.h"
+
+#include <utility>
+#include "smtp/SmtpMime"
+
+SendMailDialog::SendMailDialog(QString text, QWidget *parent)
+ : QDialog(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", QSettings::IniFormat), mText(std::move(text)) {
+
+ if (smtpAddress.isEmpty()) {
+ QMessageBox::critical(this, tr("Incomplete configuration"),
+ tr("The SMTP address is empty, please go to the setting interface to complete the configuration."));
+
+ deleteLater();
+ return;
+
+ }
+
+ senderEdit = new QLineEdit();
+ senderEdit->setText(defaultSender);
+ recipientEdit = new QTextEdit();
+ recipientEdit->setPlaceholderText("One or more email addresses. Please use ; to separate.");
+ subjectEdit = new QLineEdit();
+
+ errorLabel = new QLabel();
+
+ qDebug() << "Send Mail Settings" << smtpAddress << username << password << defaultSender << connectionTypeSettings;
+
+ confirmButton = new QPushButton("Confirm");
+
+ auto layout = new QGridLayout();
+ layout->addWidget(new QLabel("Sender"), 0, 0);
+ layout->addWidget(senderEdit, 0, 1);
+ layout->addWidget(new QLabel("Recipient"), 1, 0);
+ layout->addWidget(recipientEdit, 1, 1);
+ layout->addWidget(new QLabel("Subject"), 2, 0);
+ layout->addWidget(subjectEdit, 2, 1);
+ layout->addWidget(confirmButton, 3, 1);
+ layout->addWidget(errorLabel, 4, 0, 1, 2);
+
+ connect(confirmButton, SIGNAL(clicked(bool)), this, SLOT(slotConfirm()));
+
+ this->setLayout(layout);
+ this->setWindowTitle("Send Mail");
+ this->setModal(true);
+ this->setFixedWidth(320);
+ this->show();
+}
+
+bool SendMailDialog::check_email_address(const QString &str) {
+ return re_email.match(str).hasMatch();
+}
+
+void SendMailDialog::slotConfirm() {
+
+ QString errString;
+ errorLabel->clear();
+
+ QStringList rcptStringList = recipientEdit->toPlainText().split(';');
+
+ if (rcptStringList.isEmpty()) {
+ errString.append(tr(" Recipient cannot be empty \n"));
+ } else {
+ for (const auto& reci : rcptStringList) {
+ qDebug() << "Receiver" << reci.trimmed();
+ if (!check_email_address(reci.trimmed())) {
+ errString.append(tr(" One or more Recipient's Email Address is invalid \n"));
+ break;
+ }
+ }
+ }
+ if (senderEdit->text().isEmpty()) {
+ errString.append(tr(" Sender cannot be empty \n"));
+ } else if (!check_email_address(senderEdit->text())) {
+ errString.append(tr(" Sender's Email Address is invalid \n"));
+ }
+
+ if (!errString.isEmpty()) {
+ errorLabel->setAutoFillBackground(true);
+ QPalette error = errorLabel->palette();
+ error.setColor(QPalette::Window, "#ff8080");
+ errorLabel->setPalette(error);
+ errorLabel->setText(errString);
+ return;
+ }
+
+ SmtpClient::ConnectionType connectionType = SmtpClient::ConnectionType::TcpConnection;
+
+ if (connectionTypeSettings == "SSL") {
+ connectionType = SmtpClient::ConnectionType::SslConnection;
+ } else if (connectionTypeSettings == "TLS") {
+ connectionType = SmtpClient::ConnectionType::TlsConnection;
+ } else if (connectionTypeSettings == "STARTTLS") {
+ connectionType = SmtpClient::ConnectionType::TlsConnection;
+ } else {
+ connectionType = SmtpClient::ConnectionType::TcpConnection;
+ }
+
+ SmtpClient smtp(smtpAddress, port, connectionType);
+
+ // We need to set the username (your email address) and the password
+ // for smtp authentification.
+
+ smtp.setUser(username);
+ smtp.setPassword(password);
+
+ // Now we create a MimeMessage object. This will be the email.
+
+ MimeMessage message;
+
+ message.setSender(new EmailAddress(senderEdit->text()));
+ for (const auto &reci : rcptStringList) {
+ if(!reci.isEmpty())
+ message.addRecipient(new EmailAddress(reci.trimmed()));
+ }
+ message.setSubject(subjectEdit->text());
+
+ // Now add some text to the email.
+ // First we create a MimeText object.
+
+ MimeText text;
+
+ text.setText(mText);
+
+ // Now add it to the mail
+ message.addPart(&text);
+
+ // Now we can send the mail
+ if (!smtp.connectToHost()) {
+ qDebug() << "Connect to SMTP Server Failed";
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Connect SMTP Server"));
+ return;
+ }
+ if (!smtp.login()) {
+ qDebug() << "Login to SMTP Server Failed";
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Login into SMTP Server"));
+ return;
+ }
+ if (!smtp.sendMail(message)) {
+ qDebug() << "Send Mail to SMTP Server Failed";
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Send Mail to SMTP Server"));
+ return;
+ }
+ smtp.quit();
+
+ // Close after sending email
+ QMessageBox::information(this, tr("Success"), tr("Succeed in Sending Mail to SMTP Server"));
+ deleteLater();
+}
diff --git a/src/ui/SettingsDialog.cpp b/src/ui/SettingsDialog.cpp
index 74c507e4..1732d718 100755
--- a/src/ui/SettingsDialog.cpp
+++ b/src/ui/SettingsDialog.cpp
@@ -23,203 +23,205 @@
*/
#include "ui/SettingsDialog.h"
+#include "smtp/SmtpMime"
+#include "ui/WaitingDialog.h"
SettingsDialog::SettingsDialog(GpgME::GpgContext *ctx, QWidget *parent)
- : QDialog(parent) {
- mCtx = ctx;
- tabWidget = new QTabWidget;
- generalTab = new GeneralTab(mCtx);
- appearanceTab = new AppearanceTab;
- mimeTab = new MimeTab;
- keyserverTab = new KeyserverTab;
- advancedTab = new AdvancedTab;
- gpgPathsTab = new GpgPathsTab;
-
- tabWidget->addTab(generalTab, tr("General"));
- tabWidget->addTab(appearanceTab, tr("Appearance"));
- tabWidget->addTab(mimeTab, tr("PGP/Mime"));
- tabWidget->addTab(keyserverTab, tr("Key Server"));
- // tabWidget->addTab(gpgPathsTab, tr("Gpg paths"));
- tabWidget->addTab(advancedTab, tr("Advanced"));
-
- buttonBox =
- new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
-
- connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAccept()));
- connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(tabWidget);
- mainLayout->addWidget(buttonBox);
- setLayout(mainLayout);
-
- setWindowTitle(tr("Settings"));
-
- // slots for handling the restartneeded member
- this->slotSetRestartNeeded(false);
- connect(generalTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
- connect(appearanceTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
- connect(mimeTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
- connect(keyserverTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
- connect(advancedTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
-
- connect(this, SIGNAL(signalRestartNeeded(bool)), parent,
- SLOT(slotSetRestartNeeded(bool)));
-
- this->show();
+ : QDialog(parent) {
+ mCtx = ctx;
+ tabWidget = new QTabWidget;
+ generalTab = new GeneralTab(mCtx);
+ appearanceTab = new AppearanceTab;
+ sendMailTab = new SendMailTab;
+ keyserverTab = new KeyserverTab;
+ advancedTab = new AdvancedTab;
+ gpgPathsTab = new GpgPathsTab;
+
+ tabWidget->addTab(generalTab, tr("General"));
+ tabWidget->addTab(appearanceTab, tr("Appearance"));
+ tabWidget->addTab(sendMailTab, tr("Send Mail"));
+ tabWidget->addTab(keyserverTab, tr("Key Server"));
+ // tabWidget->addTab(gpgPathsTab, tr("Gpg paths"));
+ tabWidget->addTab(advancedTab, tr("Advanced"));
+
+ buttonBox =
+ new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAccept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(tabWidget);
+ mainLayout->addWidget(buttonBox);
+ setLayout(mainLayout);
+
+ setWindowTitle(tr("Settings"));
+
+ // slots for handling the restartneeded member
+ this->slotSetRestartNeeded(false);
+ connect(generalTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+ connect(appearanceTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+ connect(sendMailTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+ connect(keyserverTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+ connect(advancedTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+
+ connect(this, SIGNAL(signalRestartNeeded(bool)), parent,
+ SLOT(slotSetRestartNeeded(bool)));
+
+ this->show();
}
bool SettingsDialog::getRestartNeeded() const { return this->restartNeeded; }
void SettingsDialog::slotSetRestartNeeded(bool needed) {
- this->restartNeeded = needed;
+ this->restartNeeded = needed;
}
void SettingsDialog::slotAccept() {
- generalTab->applySettings();
- mimeTab->applySettings();
- appearanceTab->applySettings();
- keyserverTab->applySettings();
- advancedTab->applySettings();
- gpgPathsTab->applySettings();
- if (getRestartNeeded()) {
- emit signalRestartNeeded(true);
- }
- close();
+ generalTab->applySettings();
+ sendMailTab->applySettings();
+ appearanceTab->applySettings();
+ keyserverTab->applySettings();
+ advancedTab->applySettings();
+ gpgPathsTab->applySettings();
+ if (getRestartNeeded()) {
+ emit signalRestartNeeded(true);
+ }
+ close();
}
// http://www.informit.com/articles/article.aspx?p=1405555&seqNum=3
// http://developer.qt.nokia.com/wiki/How_to_create_a_multi_language_application
QHash<QString, QString> SettingsDialog::listLanguages() {
- QHash<QString, QString> languages;
+ QHash<QString, QString> languages;
- languages.insert("", tr("System Default"));
+ languages.insert("", tr("System Default"));
- QString appPath = qApp->applicationDirPath();
- QDir qmDir = QDir(RESOURCE_DIR(appPath) + "/ts/");
- QStringList fileNames = qmDir.entryList(QStringList("gpgfrontend_*.qm"));
+ QString appPath = qApp->applicationDirPath();
+ QDir qmDir = QDir(RESOURCE_DIR(appPath) + "/ts/");
+ QStringList fileNames = qmDir.entryList(QStringList("gpgfrontend_*.qm"));
- for (int i = 0; i < fileNames.size(); ++i) {
- QString locale = fileNames[i];
- locale.truncate(locale.lastIndexOf('.'));
- locale.remove(0, locale.indexOf('_') + 1);
+ for (int i = 0; i < fileNames.size(); ++i) {
+ QString locale = fileNames[i];
+ locale.truncate(locale.lastIndexOf('.'));
+ locale.remove(0, locale.indexOf('_') + 1);
- // this works in qt 4.8
- QLocale qloc(locale);
+ // this works in qt 4.8
+ QLocale qloc(locale);
#if QT_VERSION < 0x040800
- QString language =
- QLocale::languageToString(qloc.language()) + " (" + locale +
- ")"; //+ " (" + QLocale::languageToString(qloc.language()) + ")";
+ QString language =
+ QLocale::languageToString(qloc.language()) + " (" + locale +
+ ")"; //+ " (" + QLocale::languageToString(qloc.language()) + ")";
#else
- QString language = qloc.nativeLanguageName() + " (" + locale + ")";
+ QString language = qloc.nativeLanguageName() + " (" + locale + ")";
#endif
- languages.insert(locale, language);
- }
- return languages;
+ languages.insert(locale, language);
+ }
+ return languages;
}
GeneralTab::GeneralTab(GpgME::GpgContext *ctx, QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- mCtx = ctx;
-
- /*****************************************
- * remember Password-Box
- *****************************************/
- auto *rememberPasswordBox = new QGroupBox(tr("Remember Password"));
- auto *rememberPasswordBoxLayout = new QHBoxLayout();
- rememberPasswordCheckBox =
- new QCheckBox(tr("Remember password until closing gpg4usb"), this);
- rememberPasswordBoxLayout->addWidget(rememberPasswordCheckBox);
- rememberPasswordBox->setLayout(rememberPasswordBoxLayout);
-
- /*****************************************
- * Save-Checked-Keys-Box
- *****************************************/
- auto *saveCheckedKeysBox = new QGroupBox(tr("Save Checked Keys"));
- auto *saveCheckedKeysBoxLayout = new QHBoxLayout();
- saveCheckedKeysCheckBox = new QCheckBox(
- tr("Save checked private keys on exit and restore them on next start."),
- this);
- saveCheckedKeysBoxLayout->addWidget(saveCheckedKeysCheckBox);
- saveCheckedKeysBox->setLayout(saveCheckedKeysBoxLayout);
-
- /*****************************************
- * Key-Impport-Confirmation Box
- *****************************************/
- auto *importConfirmationBox =
- new QGroupBox(tr("Confirm drag'n'drop key import"));
- auto *importConfirmationBoxLayout = new QHBoxLayout();
- importConfirmationCheckBox = new QCheckBox(
- tr("Import files dropped on the keylist without confirmation."), this);
- importConfirmationBoxLayout->addWidget(importConfirmationCheckBox);
- importConfirmationBox->setLayout(importConfirmationBoxLayout);
-
- /*****************************************
- * Language Select Box
- *****************************************/
- auto *langBox = new QGroupBox(tr("Language"));
- auto *langBoxLayout = new QVBoxLayout();
- langSelectBox = new QComboBox;
- lang = SettingsDialog::listLanguages();
-
- foreach (QString l, lang) { langSelectBox->addItem(l); }
-
- langBoxLayout->addWidget(langSelectBox);
- langBoxLayout->addWidget(
- new QLabel(tr("<b>NOTE: </b> GpgFrontend will restart automatically if "
- "you change the language!")));
- langBox->setLayout(langBoxLayout);
- connect(langSelectBox, SIGNAL(currentIndexChanged(int)), this,
- SLOT(slotLanguageChanged()));
-
- /*****************************************
- * Own Key Select Box
- *****************************************/
- auto *ownKeyBox = new QGroupBox(tr("Own key"));
- auto *ownKeyBoxLayout = new QVBoxLayout();
- ownKeySelectBox = new QComboBox;
-
- ownKeyBox->setLayout(ownKeyBoxLayout);
- mKeyList = new KeyList(mCtx);
-
- // Fill the keyid hashmap
- keyIds.insert("", tr("<none>"));
-
- for (const auto &keyid : *mKeyList->getAllPrivateKeys()) {
- auto &key = mCtx->getKeyById(keyid);
- keyIds.insert(key.id, key.uids.first().uid);
- }
- for (const auto &k : keyIds.keys()) {
- ownKeySelectBox->addItem(keyIds.find(k).value());
- keyIdsList.append(k);
- }
- connect(ownKeySelectBox, SIGNAL(currentIndexChanged(int)), this,
- SLOT(slotOwnKeyIdChanged()));
-
- ownKeyBoxLayout->addWidget(new QLabel(
- tr("Key pair for synchronization and identity authentication")));
- ownKeyBoxLayout->addWidget(ownKeySelectBox);
-
- /*****************************************
- * Mainlayout
- *****************************************/
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(rememberPasswordBox);
- mainLayout->addWidget(saveCheckedKeysBox);
- mainLayout->addWidget(importConfirmationBox);
- mainLayout->addWidget(langBox);
- mainLayout->addWidget(ownKeyBox);
-
- setSettings();
- mainLayout->addStretch(1);
- setLayout(mainLayout);
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+ mCtx = ctx;
+
+ /*****************************************
+ * remember Password-Box
+ *****************************************/
+ auto *rememberPasswordBox = new QGroupBox(tr("Remember Password"));
+ auto *rememberPasswordBoxLayout = new QHBoxLayout();
+ rememberPasswordCheckBox =
+ new QCheckBox(tr("Remember password until closing gpg4usb"), this);
+ rememberPasswordBoxLayout->addWidget(rememberPasswordCheckBox);
+ rememberPasswordBox->setLayout(rememberPasswordBoxLayout);
+
+ /*****************************************
+ * Save-Checked-Keys-Box
+ *****************************************/
+ auto *saveCheckedKeysBox = new QGroupBox(tr("Save Checked Keys"));
+ auto *saveCheckedKeysBoxLayout = new QHBoxLayout();
+ saveCheckedKeysCheckBox = new QCheckBox(
+ tr("Save checked private keys on exit and restore them on next start."),
+ this);
+ saveCheckedKeysBoxLayout->addWidget(saveCheckedKeysCheckBox);
+ saveCheckedKeysBox->setLayout(saveCheckedKeysBoxLayout);
+
+ /*****************************************
+ * Key-Impport-Confirmation Box
+ *****************************************/
+ auto *importConfirmationBox =
+ new QGroupBox(tr("Confirm drag'n'drop key import"));
+ auto *importConfirmationBoxLayout = new QHBoxLayout();
+ importConfirmationCheckBox = new QCheckBox(
+ tr("Import files dropped on the keylist without confirmation."), this);
+ importConfirmationBoxLayout->addWidget(importConfirmationCheckBox);
+ importConfirmationBox->setLayout(importConfirmationBoxLayout);
+
+ /*****************************************
+ * Language Select Box
+ *****************************************/
+ auto *langBox = new QGroupBox(tr("Language"));
+ auto *langBoxLayout = new QVBoxLayout();
+ langSelectBox = new QComboBox;
+ lang = SettingsDialog::listLanguages();
+
+ foreach (QString l, lang) { langSelectBox->addItem(l); }
+
+ langBoxLayout->addWidget(langSelectBox);
+ langBoxLayout->addWidget(
+ new QLabel(tr("<b>NOTE: </b> GpgFrontend will restart automatically if "
+ "you change the language!")));
+ langBox->setLayout(langBoxLayout);
+ connect(langSelectBox, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(slotLanguageChanged()));
+
+ /*****************************************
+ * Own Key Select Box
+ *****************************************/
+ auto *ownKeyBox = new QGroupBox(tr("Own key"));
+ auto *ownKeyBoxLayout = new QVBoxLayout();
+ ownKeySelectBox = new QComboBox;
+
+ ownKeyBox->setLayout(ownKeyBoxLayout);
+ mKeyList = new KeyList(mCtx);
+
+ // Fill the keyid hashmap
+ keyIds.insert("", tr("<none>"));
+
+ for (const auto &keyid : *mKeyList->getAllPrivateKeys()) {
+ auto &key = mCtx->getKeyById(keyid);
+ keyIds.insert(key.id, key.uids.first().uid);
+ }
+ for (const auto &k : keyIds.keys()) {
+ ownKeySelectBox->addItem(keyIds.find(k).value());
+ keyIdsList.append(k);
+ }
+ connect(ownKeySelectBox, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(slotOwnKeyIdChanged()));
+
+ ownKeyBoxLayout->addWidget(new QLabel(
+ tr("Key pair for synchronization and identity authentication")));
+ ownKeyBoxLayout->addWidget(ownKeySelectBox);
+
+ /*****************************************
+ * Mainlayout
+ *****************************************/
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(rememberPasswordBox);
+ mainLayout->addWidget(saveCheckedKeysBox);
+ mainLayout->addWidget(importConfirmationBox);
+ mainLayout->addWidget(langBox);
+ mainLayout->addWidget(ownKeyBox);
+
+ setSettings();
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
}
/**********************************
@@ -228,32 +230,32 @@ GeneralTab::GeneralTab(GpgME::GpgContext *ctx, QWidget *parent)
* appropriately
**********************************/
void GeneralTab::setSettings() {
- // Keysaving
- if (settings.value("keys/saveKeyChecked").toBool()) {
- saveCheckedKeysCheckBox->setCheckState(Qt::Checked);
- }
-
- // Language setting
- QString langKey = settings.value("int/lang").toString();
- QString langValue = lang.value(langKey);
- if (langKey != "") {
- langSelectBox->setCurrentIndex(langSelectBox->findText(langValue));
- }
-
- QString ownKeyId = settings.value("general/ownKeyId").toString();
- qDebug() << "OwnKeyId" << ownKeyId;
- if (ownKeyId.isEmpty()) {
- ownKeySelectBox->setCurrentText("<none>");
- } else {
- const auto text = keyIds.find(ownKeyId).value();
- qDebug() << "OwnKey" << ownKeyId << text;
- ownKeySelectBox->setCurrentText(text);
- }
-
- // Get own key information from keydb/gpg.conf (if contained)
- if (settings.value("general/confirmImportKeys", Qt::Checked).toBool()) {
- importConfirmationCheckBox->setCheckState(Qt::Checked);
- }
+ // Keysaving
+ if (settings.value("keys/saveKeyChecked").toBool()) {
+ saveCheckedKeysCheckBox->setCheckState(Qt::Checked);
+ }
+
+ // Language setting
+ QString langKey = settings.value("int/lang").toString();
+ QString langValue = lang.value(langKey);
+ if (langKey != "") {
+ langSelectBox->setCurrentIndex(langSelectBox->findText(langValue));
+ }
+
+ QString ownKeyId = settings.value("general/ownKeyId").toString();
+ qDebug() << "OwnKeyId" << ownKeyId;
+ if (ownKeyId.isEmpty()) {
+ ownKeySelectBox->setCurrentText("<none>");
+ } else {
+ const auto text = keyIds.find(ownKeyId).value();
+ qDebug() << "OwnKey" << ownKeyId << text;
+ ownKeySelectBox->setCurrentText(text);
+ }
+
+ // Get own key information from keydb/gpg.conf (if contained)
+ if (settings.value("general/confirmImportKeys", Qt::Checked).toBool()) {
+ importConfirmationCheckBox->setCheckState(Qt::Checked);
+ }
}
/***********************************
@@ -261,70 +263,72 @@ void GeneralTab::setSettings() {
* write them to settings-file
*************************************/
void GeneralTab::applySettings() {
- settings.setValue("keys/saveKeyChecked",
- saveCheckedKeysCheckBox->isChecked());
- // TODO: clear passwordCache instantly on unset rememberPassword
- settings.setValue("general/rememberPassword",
- rememberPasswordCheckBox->isChecked());
- settings.setValue("int/lang", lang.key(langSelectBox->currentText()));
- settings.setValue("general/ownKeyId",
- keyIdsList[ownKeySelectBox->currentIndex()]);
- settings.setValue("general/confirmImportKeys",
- importConfirmationCheckBox->isChecked());
+ settings.setValue("keys/saveKeyChecked",
+ saveCheckedKeysCheckBox->isChecked());
+ // TODO: clear passwordCache instantly on unset rememberPassword
+ settings.setValue("general/rememberPassword",
+ rememberPasswordCheckBox->isChecked());
+ settings.setValue("int/lang", lang.key(langSelectBox->currentText()));
+ settings.setValue("general/ownKeyId",
+ keyIdsList[ownKeySelectBox->currentIndex()]);
+ settings.setValue("general/confirmImportKeys",
+ importConfirmationCheckBox->isChecked());
}
void GeneralTab::slotLanguageChanged() { emit signalRestartNeeded(true); }
void GeneralTab::slotOwnKeyIdChanged() {
- // Set ownKeyId to currently selected
+ // Set ownKeyId to currently selected
}
-MimeTab::MimeTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- /*****************************************
- * MIME-Parsing-Box
- *****************************************/
- auto *mimeQPBox = new QGroupBox(tr("Decode quoted printable"));
- auto *mimeQPBoxLayout = new QVBoxLayout();
- mimeQPCheckBox =
- new QCheckBox(tr("Try to recognize quoted printable."), this);
- mimeQPBoxLayout->addWidget(mimeQPCheckBox);
- mimeQPBox->setLayout(mimeQPBoxLayout);
-
- auto *mimeParseBox = new QGroupBox(tr("Parse PGP/MIME (Experimental)"));
- auto *mimeParseBoxLayout = new QVBoxLayout();
- mimeParseCheckBox = new QCheckBox(
- tr("Try to split attachments from PGP-MIME ecrypted messages."), this);
- mimeParseBoxLayout->addWidget(mimeParseCheckBox);
- mimeParseBox->setLayout(mimeParseBoxLayout);
-
- auto *mimeOpenAttachmentBox =
- new QGroupBox(tr("Open with external application (Experimental)"));
- auto *mimeOpenAttachmentBoxLayout = new QVBoxLayout();
- auto *mimeOpenAttachmentText = new QLabel(tr(
- "Open attachments with default application for the filetype.<br> "
- "There are at least two possible problems with this behaviour:"
- "<ol><li>File needs to be saved unencrypted to attachments folder.<br> "
- "Its your job to clean this folder.</li>"
- "<li>The external application may have its own temp files.</li></ol>"));
-
- // mimeOpenAttachmentBox->setDisabled(true);
- mimeOpenAttachmentCheckBox =
- new QCheckBox(tr("Enable opening with external applications."), this);
-
- mimeOpenAttachmentBoxLayout->addWidget(mimeOpenAttachmentText);
- mimeOpenAttachmentBoxLayout->addWidget(mimeOpenAttachmentCheckBox);
- mimeOpenAttachmentBox->setLayout(mimeOpenAttachmentBoxLayout);
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(mimeParseBox);
- mainLayout->addWidget(mimeOpenAttachmentBox);
- mainLayout->addWidget(mimeQPBox);
- mainLayout->addStretch(1);
- setLayout(mainLayout);
- setSettings();
+SendMailTab::SendMailTab(QWidget *parent)
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+
+ enableCheckBox = new QCheckBox(tr("Enable"));
+ enableCheckBox->setTristate(false);
+
+ smtpAddress = new QLineEdit();
+ username = new QLineEdit();
+ password = new QLineEdit();
+ password->setEchoMode(QLineEdit::Password);
+
+ portSpin = new QSpinBox();
+ portSpin->setMinimum(1);
+ portSpin->setMaximum(65535);
+ connectionTypeComboBox = new QComboBox();
+ connectionTypeComboBox->addItem("None");
+ connectionTypeComboBox->addItem("SSL");
+ connectionTypeComboBox->addItem("TLS");
+ connectionTypeComboBox->addItem("STARTTLS");
+
+ defaultSender = new QLineEdit();;
+ checkConnectionButton = new QPushButton("Check Connection");
+
+ auto layout = new QGridLayout();
+ layout->addWidget(enableCheckBox, 0, 0);
+ layout->addWidget(new QLabel(tr("SMTP Address")), 1, 0);
+ layout->addWidget(smtpAddress, 1, 1, 1, 4);
+ layout->addWidget(new QLabel(tr("Username")), 2, 0);
+ layout->addWidget(username, 2, 1, 1, 4);
+ layout->addWidget(new QLabel(tr("Password")), 3, 0);
+ layout->addWidget(password, 3, 1, 1, 4);
+ layout->addWidget(new QLabel(tr("Port")), 4, 0);
+ layout->addWidget(portSpin, 4, 1, 1, 1);
+ layout->addWidget(new QLabel(tr("Connection Security")), 5, 0);
+ layout->addWidget(connectionTypeComboBox, 5, 1, 1, 1);
+
+ layout->addWidget(new QLabel(tr("Default Sender")), 6, 0);
+ layout->addWidget(defaultSender, 6, 1, 1, 4);
+ layout->addWidget(checkConnectionButton, 7, 0);
+
+ connect(enableCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotCheckBoxSetEnableDisable(int)));
+ connect(checkConnectionButton, SIGNAL(clicked(bool)), this, SLOT(slotCheckConnection()));
+
+
+ this->setLayout(layout);
+ setSettings();
}
/**********************************
@@ -332,93 +336,180 @@ MimeTab::MimeTab(QWidget *parent)
* and set the buttons and checkboxes
* appropriately
**********************************/
-void MimeTab::setSettings() {
+void SendMailTab::setSettings() {
+
+ if (settings.value("sendMail/enable", false).toBool())
+ enableCheckBox->setCheckState(Qt::Checked);
+ else {
+ enableCheckBox->setCheckState(Qt::Unchecked);
+ smtpAddress->setDisabled(true);
+ username->setDisabled(true);
+ password->setDisabled(true);
+ portSpin->setDisabled(true);
+ connectionTypeComboBox->setDisabled(true);
+ defaultSender->setDisabled(true);
+ checkConnectionButton->setDisabled(true);
+ }
+
+ smtpAddress->setText(settings.value("sendMail/smtpAddress", QString()).toString());
+ username->setText(settings.value("sendMail/username", QString()).toString());
+ password->setText(settings.value("sendMail/password", QString()).toString());
+ portSpin->setValue(settings.value("sendMail/port", 25).toInt());
+ connectionTypeComboBox->setCurrentText(settings.value("sendMail/connectionType", "None").toString());
+ defaultSender->setText(settings.value("sendMail/defaultSender", QString()).toString());
- // MIME-Parsing
- if (settings.value("mime/parsemime").toBool())
- mimeParseCheckBox->setCheckState(Qt::Checked);
-
- // Qouted Printable
- if (settings.value("mime/parseQP", true).toBool())
- mimeQPCheckBox->setCheckState(Qt::Checked);
-
- // Open Attachments with external app
- if (settings.value("mime/openAttachment").toBool())
- mimeOpenAttachmentCheckBox->setCheckState(Qt::Checked);
}
/***********************************
* get the values of the buttons and
* write them to settings-file
*************************************/
-void MimeTab::applySettings() {
- settings.setValue("mime/parsemime", mimeParseCheckBox->isChecked());
- settings.setValue("mime/parseQP", mimeQPCheckBox->isChecked());
- settings.setValue("mime/openAttachment",
- mimeOpenAttachmentCheckBox->isChecked());
+void SendMailTab::applySettings() {
+
+ settings.setValue("sendMail/smtpAddress", smtpAddress->text());
+ settings.setValue("sendMail/username", username->text());
+ settings.setValue("sendMail/password", password->text());
+ settings.setValue("sendMail/port", portSpin->value());
+ settings.setValue("sendMail/connectionType", connectionTypeComboBox->currentText());
+ settings.setValue("sendMail/defaultSender", defaultSender->text());
+
+ settings.setValue("sendMail/enable", enableCheckBox->isChecked());
+}
+
+void SendMailTab::slotCheckConnection() {
+
+ SmtpClient::ConnectionType connectionType = SmtpClient::ConnectionType::TcpConnection;
+
+ if (connectionTypeComboBox->currentText() == "SSL") {
+ connectionType = SmtpClient::ConnectionType::SslConnection;
+ } else if (connectionTypeComboBox->currentText() == "TLS") {
+ connectionType = SmtpClient::ConnectionType::TlsConnection;
+ } else if (connectionTypeComboBox->currentText() == "STARTTLS") {
+ connectionType = SmtpClient::ConnectionType::TlsConnection;
+ } else {
+ connectionType = SmtpClient::ConnectionType::TcpConnection;
+ }
+
+ SmtpClient smtp(smtpAddress->text(), portSpin->value(), connectionType);
+
+ // We need to set the username (your email address) and the password
+ // for smtp authentification.
+
+ smtp.setUser(username->text());
+ smtp.setPassword(password->text());
+
+ bool if_success = true;
+
+ if (!smtp.connectToHost()) {
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Connect SMTP Server"));
+ if_success = false;
+ }
+ if (if_success && !smtp.login()) {
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Login"));
+ if_success = false;
+ }
+
+ if (if_success)
+ QMessageBox::information(this, tr("Success"), tr("Succeed in connecting and login"));
+
+}
+
+void SendMailTab::slotCheckBoxSetEnableDisable(int state) {
+ if (state == Qt::Checked) {
+ smtpAddress->setEnabled(true);
+ username->setEnabled(true);
+ password->setEnabled(true);
+ portSpin->setEnabled(true);
+ connectionTypeComboBox->setEnabled(true);
+ defaultSender->setEnabled(true);
+ checkConnectionButton->setEnabled(true);
+ } else {
+ smtpAddress->setDisabled(true);
+ username->setDisabled(true);
+ password->setDisabled(true);
+ portSpin->setDisabled(true);
+ connectionTypeComboBox->setDisabled(true);
+ defaultSender->setDisabled(true);
+ checkConnectionButton->setDisabled(true);
+ }
}
AppearanceTab::AppearanceTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- /*****************************************
- * Icon-Size-Box
- *****************************************/
- auto *iconSizeBox = new QGroupBox(tr("Iconsize"));
- iconSizeGroup = new QButtonGroup();
- iconSizeSmall = new QRadioButton(tr("small"));
- iconSizeMedium = new QRadioButton(tr("medium"));
- iconSizeLarge = new QRadioButton(tr("large"));
-
- iconSizeGroup->addButton(iconSizeSmall, 1);
- iconSizeGroup->addButton(iconSizeMedium, 2);
- iconSizeGroup->addButton(iconSizeLarge, 3);
-
- auto *iconSizeBoxLayout = new QHBoxLayout();
- iconSizeBoxLayout->addWidget(iconSizeSmall);
- iconSizeBoxLayout->addWidget(iconSizeMedium);
- iconSizeBoxLayout->addWidget(iconSizeLarge);
-
- iconSizeBox->setLayout(iconSizeBoxLayout);
-
- /*****************************************
- * Icon-Style-Box
- *****************************************/
- auto *iconStyleBox = new QGroupBox(tr("Iconstyle"));
- iconStyleGroup = new QButtonGroup();
- iconTextButton = new QRadioButton(tr("just text"));
- iconIconsButton = new QRadioButton(tr("just icons"));
- iconAllButton = new QRadioButton(tr("text and icons"));
-
- iconStyleGroup->addButton(iconTextButton, 1);
- iconStyleGroup->addButton(iconIconsButton, 2);
- iconStyleGroup->addButton(iconAllButton, 3);
-
- auto *iconStyleBoxLayout = new QHBoxLayout();
- iconStyleBoxLayout->addWidget(iconTextButton);
- iconStyleBoxLayout->addWidget(iconIconsButton);
- iconStyleBoxLayout->addWidget(iconAllButton);
-
- iconStyleBox->setLayout(iconStyleBoxLayout);
-
- /*****************************************
- * Window-Size-Box
- *****************************************/
- auto *windowSizeBox = new QGroupBox(tr("Windowstate"));
- auto *windowSizeBoxLayout = new QHBoxLayout();
- windowSizeCheckBox =
- new QCheckBox(tr("Save window size and position on exit."), this);
- windowSizeBoxLayout->addWidget(windowSizeCheckBox);
- windowSizeBox->setLayout(windowSizeBoxLayout);
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(iconSizeBox);
- mainLayout->addWidget(iconStyleBox);
- mainLayout->addWidget(windowSizeBox);
- mainLayout->addStretch(1);
- setSettings();
- setLayout(mainLayout);
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+ /*****************************************
+ * Icon-Size-Box
+ *****************************************/
+ auto *iconSizeBox = new QGroupBox(tr("Iconsize"));
+ iconSizeGroup = new QButtonGroup();
+ iconSizeSmall = new QRadioButton(tr("small"));
+ iconSizeMedium = new QRadioButton(tr("medium"));
+ iconSizeLarge = new QRadioButton(tr("large"));
+
+ iconSizeGroup->addButton(iconSizeSmall, 1);
+ iconSizeGroup->addButton(iconSizeMedium, 2);
+ iconSizeGroup->addButton(iconSizeLarge, 3);
+
+ auto *iconSizeBoxLayout = new QHBoxLayout();
+ iconSizeBoxLayout->addWidget(iconSizeSmall);
+ iconSizeBoxLayout->addWidget(iconSizeMedium);
+ iconSizeBoxLayout->addWidget(iconSizeLarge);
+
+ iconSizeBox->setLayout(iconSizeBoxLayout);
+
+ /*****************************************
+ * Icon-Style-Box
+ *****************************************/
+ auto *iconStyleBox = new QGroupBox(tr("Iconstyle"));
+ iconStyleGroup = new QButtonGroup();
+ iconTextButton = new QRadioButton(tr("just text"));
+ iconIconsButton = new QRadioButton(tr("just icons"));
+ iconAllButton = new QRadioButton(tr("text and icons"));
+
+ iconStyleGroup->addButton(iconTextButton, 1);
+ iconStyleGroup->addButton(iconIconsButton, 2);
+ iconStyleGroup->addButton(iconAllButton, 3);
+
+ auto *iconStyleBoxLayout = new QHBoxLayout();
+ iconStyleBoxLayout->addWidget(iconTextButton);
+ iconStyleBoxLayout->addWidget(iconIconsButton);
+ iconStyleBoxLayout->addWidget(iconAllButton);
+
+ iconStyleBox->setLayout(iconStyleBoxLayout);
+
+ /*****************************************
+ * Window-Size-Box
+ *****************************************/
+ auto *windowSizeBox = new QGroupBox(tr("Windowstate"));
+ auto *windowSizeBoxLayout = new QHBoxLayout();
+ windowSizeCheckBox =
+ new QCheckBox(tr("Save window size and position on exit."), this);
+ windowSizeBoxLayout->addWidget(windowSizeCheckBox);
+ windowSizeBox->setLayout(windowSizeBoxLayout);
+
+ /*****************************************
+ * Info-Board-Font-Size-Box
+ *****************************************/
+
+ auto *infoBoardBox = new QGroupBox(tr("Information Board"));
+ auto *infoBoardLayout = new QHBoxLayout();
+ infoBoardFontSizeSpin = new QSpinBox();
+ infoBoardFontSizeSpin->setRange(9, 18);
+ infoBoardFontSizeSpin->setValue(10);
+ infoBoardFontSizeSpin->setSingleStep(1);
+ infoBoardLayout->addWidget(new QLabel(tr(" Front Size")));
+ infoBoardLayout->addWidget(infoBoardFontSizeSpin);
+ infoBoardBox->setLayout(infoBoardLayout);
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(iconSizeBox);
+ mainLayout->addWidget(iconStyleBox);
+ mainLayout->addWidget(windowSizeBox);
+ mainLayout->addWidget(infoBoardBox);
+ mainLayout->addStretch(1);
+ setSettings();
+ setLayout(mainLayout);
}
/**********************************
@@ -428,40 +519,46 @@ AppearanceTab::AppearanceTab(QWidget *parent)
**********************************/
void AppearanceTab::setSettings() {
- // Iconsize
- QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
- switch (iconSize.height()) {
- case 12:
- iconSizeSmall->setChecked(true);
- break;
- case 24:
- iconSizeMedium->setChecked(true);
- break;
- case 32:
- iconSizeLarge->setChecked(true);
- break;
- }
- // Iconstyle
- Qt::ToolButtonStyle iconStyle = static_cast<Qt::ToolButtonStyle>(
- settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
- .toUInt());
- switch (iconStyle) {
- case Qt::ToolButtonTextOnly:
- iconTextButton->setChecked(true);
- break;
- case Qt::ToolButtonIconOnly:
- iconIconsButton->setChecked(true);
- break;
- case Qt::ToolButtonTextUnderIcon:
- iconAllButton->setChecked(true);
- break;
- default:
- break;
- }
-
- // Window Save and Position
- if (settings.value("window/windowSave").toBool())
- windowSizeCheckBox->setCheckState(Qt::Checked);
+ // Iconsize
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
+ switch (iconSize.height()) {
+ case 12:
+ iconSizeSmall->setChecked(true);
+ break;
+ case 24:
+ iconSizeMedium->setChecked(true);
+ break;
+ case 32:
+ iconSizeLarge->setChecked(true);
+ break;
+ }
+ // Iconstyle
+ Qt::ToolButtonStyle iconStyle = static_cast<Qt::ToolButtonStyle>(
+ settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
+ .toUInt());
+ switch (iconStyle) {
+ case Qt::ToolButtonTextOnly:
+ iconTextButton->setChecked(true);
+ break;
+ case Qt::ToolButtonIconOnly:
+ iconIconsButton->setChecked(true);
+ break;
+ case Qt::ToolButtonTextUnderIcon:
+ iconAllButton->setChecked(true);
+ break;
+ default:
+ break;
+ }
+
+ // Window Save and Position
+ if (settings.value("window/windowSave").toBool())
+ windowSizeCheckBox->setCheckState(Qt::Checked);
+
+ // infoBoardFontSize
+ auto infoBoardFontSize = settings.value("informationBoard/fontSize", 10).toInt();
+ if (infoBoardFontSize < 9 || infoBoardFontSize > 18)
+ infoBoardFontSize = 10;
+ infoBoardFontSizeSpin->setValue(infoBoardFontSize);
}
/***********************************
@@ -469,72 +566,74 @@ void AppearanceTab::setSettings() {
* write them to settings-file
*************************************/
void AppearanceTab::applySettings() {
- switch (iconSizeGroup->checkedId()) {
- case 1:
- settings.setValue("toolbar/iconsize", QSize(12, 12));
- break;
- case 2:
- settings.setValue("toolbar/iconsize", QSize(24, 24));
- break;
- case 3:
- settings.setValue("toolbar/iconsize", QSize(32, 32));
- break;
- }
-
- switch (iconStyleGroup->checkedId()) {
- case 1:
- settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextOnly);
- break;
- case 2:
- settings.setValue("toolbar/iconstyle", Qt::ToolButtonIconOnly);
- break;
- case 3:
- settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon);
- break;
- }
-
- settings.setValue("window/windowSave", windowSizeCheckBox->isChecked());
+ switch (iconSizeGroup->checkedId()) {
+ case 1:
+ settings.setValue("toolbar/iconsize", QSize(12, 12));
+ break;
+ case 2:
+ settings.setValue("toolbar/iconsize", QSize(24, 24));
+ break;
+ case 3:
+ settings.setValue("toolbar/iconsize", QSize(32, 32));
+ break;
+ }
+
+ switch (iconStyleGroup->checkedId()) {
+ case 1:
+ settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextOnly);
+ break;
+ case 2:
+ settings.setValue("toolbar/iconstyle", Qt::ToolButtonIconOnly);
+ break;
+ case 3:
+ settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon);
+ break;
+ }
+
+ settings.setValue("window/windowSave", windowSizeCheckBox->isChecked());
+
+ settings.setValue("informationBoard/fontSize", infoBoardFontSizeSpin->value());
}
KeyserverTab::KeyserverTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
-
- auto keyServerList = settings.value("keyserver/keyServerList").toStringList();
-
- auto *mainLayout = new QVBoxLayout(this);
-
- auto *label = new QLabel(tr("Default Keyserver for import:"));
- comboBox = new QComboBox;
- comboBox->setEditable(false);
- comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
-
- for (const auto &keyServer : keyServerList) {
- comboBox->addItem(keyServer);
- qDebug() << "KeyserverTab Get ListItemText" << keyServer;
- }
-
- comboBox->setCurrentText(
- settings.value("keyserver/defaultKeyServer").toString());
-
- auto *addKeyServerBox = new QWidget(this);
- auto *addKeyServerLayout = new QHBoxLayout(addKeyServerBox);
- auto *http = new QLabel("URL: ");
- newKeyServerEdit = new QLineEdit(this);
- auto *newKeyServerButton = new QPushButton(tr("Add"), this);
- connect(newKeyServerButton, SIGNAL(clicked()), this, SLOT(addKeyServer()));
- addKeyServerLayout->addWidget(http);
- addKeyServerLayout->addWidget(newKeyServerEdit);
- addKeyServerLayout->addWidget(newKeyServerButton);
-
- mainLayout->addWidget(label);
- mainLayout->addWidget(comboBox);
- mainLayout->addWidget(addKeyServerBox);
- mainLayout->addStretch(1);
-
- // Read keylist from ini-file and fill it into combobox
- setSettings();
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+
+ auto keyServerList = settings.value("keyserver/keyServerList").toStringList();
+
+ auto *mainLayout = new QVBoxLayout(this);
+
+ auto *label = new QLabel(tr("Default Key Server for import:"));
+ comboBox = new QComboBox;
+ comboBox->setEditable(false);
+ comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+ for (const auto &keyServer : keyServerList) {
+ comboBox->addItem(keyServer);
+ qDebug() << "KeyserverTab Get ListItemText" << keyServer;
+ }
+
+ comboBox->setCurrentText(
+ settings.value("keyserver/defaultKeyServer").toString());
+
+ auto *addKeyServerBox = new QWidget(this);
+ auto *addKeyServerLayout = new QHBoxLayout(addKeyServerBox);
+ auto *http = new QLabel("URL: ");
+ newKeyServerEdit = new QLineEdit(this);
+ auto *newKeyServerButton = new QPushButton(tr("Add"), this);
+ connect(newKeyServerButton, SIGNAL(clicked()), this, SLOT(addKeyServer()));
+ addKeyServerLayout->addWidget(http);
+ addKeyServerLayout->addWidget(newKeyServerEdit);
+ addKeyServerLayout->addWidget(newKeyServerButton);
+
+ mainLayout->addWidget(label);
+ mainLayout->addWidget(comboBox);
+ mainLayout->addWidget(addKeyServerBox);
+ mainLayout->addStretch(1);
+
+ // Read keylist from ini-file and fill it into combobox
+ setSettings();
}
/**********************************
@@ -543,23 +642,23 @@ KeyserverTab::KeyserverTab(QWidget *parent)
* appropriately
**********************************/
void KeyserverTab::setSettings() {
- auto *keyServerList = new QStringList();
- for (int i = 0; i < comboBox->count(); i++) {
- keyServerList->append(comboBox->itemText(i));
- qDebug() << "KeyserverTab ListItemText" << comboBox->itemText(i);
- }
- settings.setValue("keyserver/keyServerList", *keyServerList);
- settings.setValue("keyserver/defaultKeyServer", comboBox->currentText());
+ auto *keyServerList = new QStringList();
+ for (int i = 0; i < comboBox->count(); i++) {
+ keyServerList->append(comboBox->itemText(i));
+ qDebug() << "KeyserverTab ListItemText" << comboBox->itemText(i);
+ }
+ settings.setValue("keyserver/keyServerList", *keyServerList);
+ settings.setValue("keyserver/defaultKeyServer", comboBox->currentText());
}
void KeyserverTab::addKeyServer() {
- if (newKeyServerEdit->text().startsWith("http://") ||
- newKeyServerEdit->text().startsWith("https://")) {
- comboBox->addItem(newKeyServerEdit->text());
- } else {
- comboBox->addItem("http://" + newKeyServerEdit->text());
- }
- comboBox->setCurrentIndex(comboBox->count() - 1);
+ if (newKeyServerEdit->text().startsWith("http://") ||
+ newKeyServerEdit->text().startsWith("https://")) {
+ comboBox->addItem(newKeyServerEdit->text());
+ } else {
+ comboBox->addItem("http://" + newKeyServerEdit->text());
+ }
+ comboBox->setCurrentIndex(comboBox->count() - 1);
}
/***********************************
@@ -567,112 +666,112 @@ void KeyserverTab::addKeyServer() {
* write them to settings-file
*************************************/
void KeyserverTab::applySettings() {
- settings.setValue("keyserver/defaultKeyServer", comboBox->currentText());
+ settings.setValue("keyserver/defaultKeyServer", comboBox->currentText());
}
AdvancedTab::AdvancedTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- /*****************************************
- * Steganography Box
- *****************************************/
- auto *steganoBox = new QGroupBox(tr("Show Steganography Options [Advanced]"));
- auto *steganoBoxLayout = new QHBoxLayout();
- steganoCheckBox = new QCheckBox(tr("Show Steganographic Options."), this);
- steganoBoxLayout->addWidget(steganoCheckBox);
- steganoBox->setLayout(steganoBoxLayout);
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(steganoBox);
- setSettings();
- mainLayout->addStretch(1);
- setLayout(mainLayout);
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+ /*****************************************
+ * Steganography Box
+ *****************************************/
+ auto *steganoBox = new QGroupBox(tr("Show Steganography Options [Advanced]"));
+ auto *steganoBoxLayout = new QHBoxLayout();
+ steganoCheckBox = new QCheckBox(tr("Show Steganographic Options."), this);
+ steganoBoxLayout->addWidget(steganoCheckBox);
+ steganoBox->setLayout(steganoBoxLayout);
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(steganoBox);
+ setSettings();
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
}
void AdvancedTab::setSettings() {
- if (settings.value("advanced/steganography").toBool()) {
- steganoCheckBox->setCheckState(Qt::Checked);
- }
+ if (settings.value("advanced/steganography").toBool()) {
+ steganoCheckBox->setCheckState(Qt::Checked);
+ }
}
void AdvancedTab::applySettings() {
- settings.setValue("advanced/steganography", steganoCheckBox->isChecked());
+ settings.setValue("advanced/steganography", steganoCheckBox->isChecked());
}
GpgPathsTab::GpgPathsTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- setSettings();
-
- /*****************************************
- * Keydb Box
- *****************************************/
- auto *keydbBox = new QGroupBox(tr("Relative path to keydb"));
- auto *keydbBoxLayout = new QGridLayout();
-
- // Label containing the current keydbpath relative to default keydb path
- keydbLabel = new QLabel(accKeydbPath, this);
-
- auto *keydbButton = new QPushButton("Change keydb path", this);
- connect(keydbButton, SIGNAL(clicked()), this, SLOT(chooseKeydbDir()));
- auto *keydbDefaultButton = new QPushButton("Set keydb to default path", this);
- connect(keydbDefaultButton, SIGNAL(clicked()), this,
- SLOT(setKeydbPathToDefault()));
-
- keydbBox->setLayout(keydbBoxLayout);
- keydbBoxLayout->addWidget(new QLabel(tr("Current keydb path: ")), 1, 1);
- keydbBoxLayout->addWidget(keydbLabel, 1, 2);
- keydbBoxLayout->addWidget(keydbButton, 1, 3);
- keydbBoxLayout->addWidget(keydbDefaultButton, 2, 3);
- keydbBoxLayout->addWidget(
- new QLabel(tr("<b>NOTE: </b> Gpg4usb will restart automatically if you "
- "change the keydb path!")),
- 3, 1, 1, 3);
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(keydbBox);
- mainLayout->addStretch(1);
- setLayout(mainLayout);
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+ setSettings();
+
+ /*****************************************
+ * Keydb Box
+ *****************************************/
+ auto *keydbBox = new QGroupBox(tr("Relative path to keydb"));
+ auto *keydbBoxLayout = new QGridLayout();
+
+ // Label containing the current keydbpath relative to default keydb path
+ keydbLabel = new QLabel(accKeydbPath, this);
+
+ auto *keydbButton = new QPushButton("Change keydb path", this);
+ connect(keydbButton, SIGNAL(clicked()), this, SLOT(chooseKeydbDir()));
+ auto *keydbDefaultButton = new QPushButton("Set keydb to default path", this);
+ connect(keydbDefaultButton, SIGNAL(clicked()), this,
+ SLOT(setKeydbPathToDefault()));
+
+ keydbBox->setLayout(keydbBoxLayout);
+ keydbBoxLayout->addWidget(new QLabel(tr("Current keydb path: ")), 1, 1);
+ keydbBoxLayout->addWidget(keydbLabel, 1, 2);
+ keydbBoxLayout->addWidget(keydbButton, 1, 3);
+ keydbBoxLayout->addWidget(keydbDefaultButton, 2, 3);
+ keydbBoxLayout->addWidget(
+ new QLabel(tr("<b>NOTE: </b> Gpg4usb will restart automatically if you "
+ "change the keydb path!")),
+ 3, 1, 1, 3);
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(keydbBox);
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
}
QString GpgPathsTab::getRelativePath(const QString &dir1, const QString &dir2) {
- QDir dir(dir1);
- QString s;
-
- s = dir.relativeFilePath(dir2);
- qDebug() << "relative path: " << s;
- if (s.isEmpty()) {
- s = ".";
- }
- return s;
+ QDir dir(dir1);
+ QString s;
+
+ s = dir.relativeFilePath(dir2);
+ qDebug() << "relative path: " << s;
+ if (s.isEmpty()) {
+ s = ".";
+ }
+ return s;
}
void GpgPathsTab::setKeydbPathToDefault() {
- accKeydbPath = ".";
- keydbLabel->setText(".");
+ accKeydbPath = ".";
+ keydbLabel->setText(".");
}
QString GpgPathsTab::chooseKeydbDir() {
- QString dir = QFileDialog::getExistingDirectory(
- this, tr("Choose keydb directory"), accKeydbPath,
- QFileDialog::ShowDirsOnly);
+ QString dir = QFileDialog::getExistingDirectory(
+ this, tr("Choose keydb directory"), accKeydbPath,
+ QFileDialog::ShowDirsOnly);
- accKeydbPath = getRelativePath(defKeydbPath, dir);
- keydbLabel->setText(accKeydbPath);
- return "";
+ accKeydbPath = getRelativePath(defKeydbPath, dir);
+ keydbLabel->setText(accKeydbPath);
+ return "";
}
void GpgPathsTab::setSettings() {
- defKeydbPath = qApp->applicationDirPath() + "/keydb";
+ defKeydbPath = qApp->applicationDirPath() + "/keydb";
- accKeydbPath = settings.value("gpgpaths/keydbpath").toString();
- if (accKeydbPath.isEmpty()) {
- accKeydbPath = ".";
- }
+ accKeydbPath = settings.value("gpgpaths/keydbpath").toString();
+ if (accKeydbPath.isEmpty()) {
+ accKeydbPath = ".";
+ }
}
void GpgPathsTab::applySettings() {
- settings.setValue("gpgpaths/keydbpath", accKeydbPath);
+ settings.setValue("gpgpaths/keydbpath", accKeydbPath);
}
diff --git a/src/ui/WaitingDialog.cpp b/src/ui/WaitingDialog.cpp
index 8281385a..daccc3ca 100644
--- a/src/ui/WaitingDialog.cpp
+++ b/src/ui/WaitingDialog.cpp
@@ -1,15 +1,20 @@
#include "ui/WaitingDialog.h"
-WaitingDialog::WaitingDialog(QWidget *parent) : QDialog(parent) {
+WaitingDialog::WaitingDialog(const QString &title, QWidget *parent) : QDialog(parent) {
auto *pb = new QProgressBar();
pb->setRange(0, 0);
+ pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ pb->setTextVisible(false);
auto *layout = new QVBoxLayout();
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
layout->addWidget(pb);
this->setLayout(layout);
this->setModal(true);
- this->setWindowTitle(tr("Processing"));
+ this->setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
+ this->setWindowTitle(title);
this->setFixedSize(240, 42);
this->show();
}
diff --git a/src/ui/Wizard.cpp b/src/ui/Wizard.cpp
index 456e8c52..b0486cc9 100644
--- a/src/ui/Wizard.cpp
+++ b/src/ui/Wizard.cpp
@@ -108,16 +108,20 @@ bool Wizard::importPubAndSecKeysFromDir(const QString &dir, KeyMgmt *keyMgmt) {
IntroPage::IntroPage(QWidget *parent)
: QWizardPage(parent), appPath(qApp->applicationDirPath()),
settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", QSettings::IniFormat) {
- setTitle(tr("Getting started..."));
+ setTitle(tr("Getting Started..."));
setSubTitle(tr("... with GPGFrontend"));
- auto *topLabel = new QLabel(tr("To use GPGFrontend for decrypting and signing messages, you need a "
- "private key. The next page will help you with "
- "key generation or import.<br><br>"
- "For more information have a look at the <a href='docu_concepts.html'>concepts</a> "
- "(by clicking the link, the page will open in the main window). <br>"));
+ auto *topLabel = new QLabel(tr("Welcome to use GPGFrontend for decrypting and signing text or file!")+
+ " <br><br><a href='https://github.com/saturneric/GpgFrontend'>GpgFrontend</a> " +
+ tr("is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.") +
+ tr("For brief information have a look at the") + "<a href='https://saturneric.github.io/GpgFrontend/index.html#/overview'>"+
+ tr("Overview") +"</a> (" +
+ tr("by clicking the link, the page will open in the web browser") +
+ "). <br>");
+ topLabel->setTextFormat(Qt::RichText);
+ topLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ topLabel->setOpenExternalLinks(true);
topLabel->setWordWrap(true);
- // connect(topLabel, SIGNAL(linkActivated(QString)), parentWidget()->parentWidget(), SLOT(openHelp(QString)));
// QComboBox for language selection
auto *langLabel = new QLabel(tr("Choose a Language"));
@@ -126,9 +130,9 @@ IntroPage::IntroPage(QWidget *parent)
languages = SettingsDialog::listLanguages();
auto *langSelectBox = new QComboBox();
- foreach(QString l, languages) {
- langSelectBox->addItem(l);
- }
+ for(const auto &l : languages) {
+ langSelectBox->addItem(l);
+ }
// selected entry from config
QString langKey = settings.value("int/lang").toString();
QString langValue = languages.value(langKey);
@@ -162,25 +166,31 @@ ChoosePage::ChoosePage(QWidget *parent)
setSubTitle(tr("...by clicking on the appropriate link."));
auto *keygenLabel = new QLabel(tr("If you have never used GPGFrontend before and also don't own a gpg key yet you "
- "may possibly want to read how to") + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/generate-key\">"
- + tr("create a new keypair") + "</a><hr>");
+ "may possibly want to read how to") + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/generate-key\">"
+ + tr("Generate Key") + "</a><hr>");
keygenLabel->setTextFormat(Qt::RichText);
keygenLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
keygenLabel->setOpenExternalLinks(true);
keygenLabel->setWordWrap(true);
- auto *encrDecyTextLabel = new QLabel(tr("If you want to learn how to encrypt and decrypt text, you can read ")
+ auto *encrDecyTextLabel = new QLabel(tr("If you want to learn how to encrypt, decrypt, sign and verify text, you can read ")
+ "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/encrypt-decrypt-text\">"
- + tr("this document") + "</a><hr>");
+ + tr("Encrypt & Decrypt Text") + "</a> " + tr("or")
+ + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-text\">"
+ + tr("Sign & Verify Text")
+ +"</a><hr>");
encrDecyTextLabel->setTextFormat(Qt::RichText);
encrDecyTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
encrDecyTextLabel->setOpenExternalLinks(true);
encrDecyTextLabel->setWordWrap(true);
- auto *signVerifyTextLabel = new QLabel(tr("If you want to sign and verify text, you can read ")
- + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-text\">"
- + tr("this document") + "</a>");
+ auto *signVerifyTextLabel = new QLabel(tr("If you want to operate file, you can read ")
+ + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/encrypt-decrypt-file\">"
+ + tr("Encrypt & Sign File") + "</a> " + tr("or")
+ + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-file\">"
+ + tr("Sign & Verify File")
+ +"</a><hr>");
signVerifyTextLabel->setTextFormat(Qt::RichText);
signVerifyTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
signVerifyTextLabel->setOpenExternalLinks(true);
diff --git a/src/ui/help/AboutDialog.cpp b/src/ui/help/AboutDialog.cpp
new file mode 100644
index 00000000..807c509d
--- /dev/null
+++ b/src/ui/help/AboutDialog.cpp
@@ -0,0 +1,215 @@
+/**
+ * This file is part of GPGFrontend.
+ *
+ * GPGFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#include "ui/help/AboutDialog.h"
+#include "GpgFrontendBuildInfo.h"
+
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+
+using namespace rapidjson;
+
+AboutDialog::AboutDialog(int defaultIndex, QWidget *parent)
+ : QDialog(parent) {
+ this->setWindowTitle(tr("About ") + qApp->applicationName());
+
+ auto *tabWidget = new QTabWidget;
+ auto *infoTab = new InfoTab();
+ auto *translatorsTab = new TranslatorsTab();
+ auto *updateTab = new UpdateTab();
+
+ tabWidget->addTab(infoTab, tr("General"));
+ tabWidget->addTab(translatorsTab, tr("Translators"));
+ tabWidget->addTab(updateTab, tr("Update"));
+
+ connect(tabWidget, &QTabWidget::currentChanged, this, [&](int index) {
+ qDebug() << "Current Index" << index;
+ if(index == 2) {
+ updateTab->getLatestVersion();
+ }
+ });
+
+ if(defaultIndex < tabWidget->count() && defaultIndex >= 0) {
+ tabWidget->setCurrentIndex(defaultIndex);
+ }
+
+ auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(tabWidget);
+ mainLayout->addWidget(buttonBox);
+ setLayout(mainLayout);
+
+ this->exec();
+}
+
+InfoTab::InfoTab(QWidget *parent)
+ : QWidget(parent) {
+ auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
+ auto *text = new QString("<center><h2>" + qApp->applicationName() + "</h2></center>"
+ + "<center><b>" + qApp->applicationVersion() + "</b></center>"
+ + "<center>" + GIT_VERSION + "</center>"
+ + tr("<br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>"
+ "and installation-free gpg front-end tool.<br>"
+ "It visualizes most of the common operations of gpg commands.<br>"
+ "It's licensed under the GPL v3<br><br>"
+ "<b>Developer:</b><br>"
+ "Saturneric<br><br>"
+ "If you have any questions or suggestions, raise an issue<br/>"
+ "at <a href=\"https://github.com/saturneric/GpgFrontend\">GitHub</a> or send a mail to my mailing list at <a href=\"mailto:[email protected]\">[email protected]</a>.") +
+ tr("<br><br> Built with Qt ") + qVersion()
+ + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() +
+ tr("<br>Built at ") + BUILD_TIMESTAMP + "</center>");
+
+ auto *layout = new QGridLayout();
+ auto *pixmapLabel = new QLabel();
+ pixmapLabel->setPixmap(*pixmap);
+ layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+ auto *aboutLabel = new QLabel();
+ aboutLabel->setText(*text);
+ aboutLabel->setOpenExternalLinks(true);
+ layout->addWidget(aboutLabel, 1, 0, 1, -1);
+ layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
+ QSizePolicy::Fixed), 2, 1, 1, 1);
+
+ setLayout(layout);
+}
+
+TranslatorsTab::TranslatorsTab(QWidget *parent)
+ : QWidget(parent) {
+ QFile translatorsFile;
+ translatorsFile.setFileName(qApp->applicationDirPath() + "/About");
+ translatorsFile.open(QIODevice::ReadOnly);
+ QByteArray inBuffer = translatorsFile.readAll();
+
+ auto *label = new QLabel(inBuffer);
+ auto *mainLayout = new QVBoxLayout(this);
+ mainLayout->addWidget(label);
+
+ setLayout(mainLayout);
+}
+
+UpdateTab::UpdateTab(QWidget *parent) {
+ auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
+ auto *layout = new QGridLayout();
+ auto *pixmapLabel = new QLabel();
+ pixmapLabel->setPixmap(*pixmap);
+ layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+
+ currentVersion = "v" + QString::number(VERSION_MAJOR) + "."
+ + QString::number(VERSION_MINOR) + "."
+ + QString::number(VERSION_PATCH);
+
+ auto tipsLabel = new QLabel();
+ tipsLabel->setText("<center>" +
+ tr("It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.") +
+ "</center><br><center>" +
+ tr("New versions not only represent new features, but also often represent functional and security fixes.") + "</center>");
+ tipsLabel->setWordWrap(true);
+
+ currentVersionLabel = new QLabel();
+ currentVersionLabel->setText("<center>" + tr("Current Version: ") + "<b>" + currentVersion + "</b></center>");
+ currentVersionLabel->setWordWrap(true);
+
+ latestVersionLabel = new QLabel();
+ latestVersionLabel->setWordWrap(true);
+
+ upgradeLabel = new QLabel();
+ upgradeLabel->setText("<center>" +
+ tr("The current version is inconsistent with the latest version on github.") +
+ "</center><br><center>" +
+ tr("Please click <a href=\"https://github.com/saturneric/GpgFrontend/releases\">here</a> to download the latest version.") + "</center>");
+ upgradeLabel->setWordWrap(true);
+ upgradeLabel->setOpenExternalLinks(true);
+ upgradeLabel->setHidden(true);
+
+ pb = new QProgressBar();
+ pb->setRange(0, 0);
+ pb->setTextVisible(false);
+
+ layout->addWidget(tipsLabel, 1, 0, 1, -1);
+ layout->addWidget(currentVersionLabel, 2, 0, 1, -1);
+ layout->addWidget(latestVersionLabel, 3, 0, 1, -1);
+ layout->addWidget(upgradeLabel, 4, 0, 1, -1);
+ layout->addWidget(pb, 5, 0, 1, -1);
+ layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
+ QSizePolicy::Fixed), 2, 1, 1, 1);
+
+ setLayout(layout);
+}
+
+void UpdateTab::getLatestVersion() {
+
+ this->pb->setHidden(false);
+
+ qDebug() << "Try to get latest version";
+
+ QString baseUrl = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest";
+
+ auto manager = new QNetworkAccessManager(this);
+
+ QNetworkRequest request;
+ request.setUrl(QUrl(baseUrl));
+
+ QNetworkReply *replay = manager->get(request);
+
+ while(replay->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ this->pb->setHidden(true);
+
+ if(replay->error() != QNetworkReply::NoError) {
+ qDebug() << "VersionCheckThread Found Network Error";
+ auto latestVersion = "Unknown";
+ latestVersionLabel->setText("<center><b>" + tr("Latest Version From Github: ") + latestVersion + "</b></center>");
+ return;
+ }
+
+ QByteArray bytes = replay->readAll();
+
+ Document d;
+ d.Parse(bytes.constData());
+
+ QString latestVersion = d["tag_name"].GetString();
+
+ qDebug() << "Latest Version From Github" << latestVersion;
+
+ QRegularExpression re("^[vV](\\d+\\.)?(\\d+\\.)?(\\*|\\d+)");
+ QRegularExpressionMatch match = re.match(latestVersion);
+ if (match.hasMatch()) {
+ latestVersion = match.captured(0); // matched == "23 def"
+ qDebug() << "Latest Version Matched" << latestVersion;
+ } else {
+ latestVersion = "Unknown";
+ }
+
+ latestVersionLabel->setText("<center><b>" + tr("Latest Version From Github: ") + latestVersion + "</b></center>");
+
+ if(latestVersion > currentVersion) {
+ upgradeLabel->setHidden(false);
+ }
+
+}
diff --git a/src/ui/help/VersionCheckThread.cpp b/src/ui/help/VersionCheckThread.cpp
new file mode 100644
index 00000000..c7c77d1c
--- /dev/null
+++ b/src/ui/help/VersionCheckThread.cpp
@@ -0,0 +1,55 @@
+//
+// Created by Administrator on 2021/7/12.
+//
+
+#include "ui/help/VersionCheckThread.h"
+#include "GpgFrontendBuildInfo.h"
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+
+using namespace rapidjson;
+
+void VersionCheckThread::run() {
+ qDebug() << "Start Version Thread to get latest version from Github";
+
+ auto currentVersion = "v" + QString::number(VERSION_MAJOR) + "."
+ + QString::number(VERSION_MINOR) + "."
+ + QString::number(VERSION_PATCH);
+
+ while(mNetworkReply->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ if(mNetworkReply->error() != QNetworkReply::NoError) {
+ qDebug() << "VersionCheckThread Found Network Error";
+ return;
+ }
+
+ QByteArray bytes = mNetworkReply->readAll();
+
+ Document d;
+ d.Parse(bytes.constData());
+
+ QString latestVersion = d["tag_name"].GetString();
+
+ qDebug() << "Latest Version From Github" << latestVersion;
+
+ QRegularExpression re("^[vV](\\d+\\.)?(\\d+\\.)?(\\*|\\d+)");
+ QRegularExpressionMatch match = re.match(latestVersion);
+ if (match.hasMatch()) {
+ latestVersion = match.captured(0); // matched == "23 def"
+ qDebug() << "Latest Version Matched" << latestVersion;
+ } else {
+ latestVersion = currentVersion;
+ qDebug() << "Latest Version Unknown" << latestVersion;
+ }
+
+ if(latestVersion != currentVersion) {
+ emit upgradeVersion(currentVersion, latestVersion);
+ }
+
+}
+
+VersionCheckThread::VersionCheckThread(QNetworkReply *networkReply):mNetworkReply(networkReply) {
+
+}
diff --git a/src/ui/keygen/KeygenDialog.cpp b/src/ui/keygen/KeygenDialog.cpp
index b9fdae3f..7991ddd1 100644
--- a/src/ui/keygen/KeygenDialog.cpp
+++ b/src/ui/keygen/KeygenDialog.cpp
@@ -74,8 +74,7 @@ void KeyGenDialog::slotKeyGenAccept() {
* primary keys should have a reasonable expiration date (no more than 2 years in the future)
*/
if(dateEdit->dateTime() > QDateTime::currentDateTime().addYears(2)) {
-
- errorString.append(tr(" Expiration time no more than 2 years. "));
+ errorString.append(tr(" Expiration time no more than 2 years. \n"));
}
if (errorString.isEmpty()) {
@@ -148,7 +147,7 @@ QGroupBox *KeyGenDialog::create_key_usage_group_box() {
auto *groupBox = new QGroupBox(this);
auto *grid = new QGridLayout(this);
- groupBox->setTitle("Key Usage");
+ groupBox->setTitle(tr("Key Usage"));
auto* encrypt = new QCheckBox(tr("Encryption"), groupBox);
encrypt->setTristate(false);
diff --git a/src/ui/keygen/SubkeyGenerateThread.cpp b/src/ui/keygen/SubkeyGenerateThread.cpp
index 4f19ac1f..125f35f8 100644
--- a/src/ui/keygen/SubkeyGenerateThread.cpp
+++ b/src/ui/keygen/SubkeyGenerateThread.cpp
@@ -24,8 +24,6 @@
#include "ui/keygen/SubkeyGenerateThread.h"
-#include <utility>
-
SubkeyGenerateThread::SubkeyGenerateThread(GpgKey key, GenKeyInfo *keyGenParams, GpgME::GpgContext *ctx)
: mKey(std::move(key)), keyGenParams(keyGenParams) , mCtx(ctx) {
connect(this, &SubkeyGenerateThread::finished, this, &SubkeyGenerateThread::deleteLater);
diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp
index 013d8e11..9ca4e37e 100644
--- a/src/ui/keypair_details/KeyPairDetailTab.cpp
+++ b/src/ui/keypair_details/KeyPairDetailTab.cpp
@@ -23,8 +23,10 @@
*/
#include "ui/keypair_details/KeyPairDetailTab.h"
+#include "ui/WaitingDialog.h"
-KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, QWidget *parent) : mKey(mKey), QWidget(parent) {
+KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, QWidget *parent) : mKey(mKey),
+ QWidget(parent) {
mCtx = ctx;
keyid = new QString(mKey.id);
@@ -53,8 +55,8 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
algorithmVarLabel = new QLabel();
// Show the situation that master key not exists.
- masterKeyExistVarLabel = new QLabel(mKey.has_master_key ? "Exists" : "Not Exists");
- if(!mKey.has_master_key){
+ masterKeyExistVarLabel = new QLabel(mKey.has_master_key ? tr("Exists") : tr("Not Exists"));
+ if (!mKey.has_master_key) {
auto paletteExpired = masterKeyExistVarLabel->palette();
paletteExpired.setColor(masterKeyExistVarLabel->foregroundRole(), Qt::red);
masterKeyExistVarLabel->setPalette(paletteExpired);
@@ -64,7 +66,7 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
masterKeyExistVarLabel->setPalette(paletteValid);
}
- if(mKey.expired){
+ if (mKey.expired) {
auto paletteExpired = expireVarLabel->palette();
paletteExpired.setColor(expireVarLabel->foregroundRole(), Qt::red);
expireVarLabel->setPalette(paletteExpired);
@@ -131,18 +133,27 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
auto *privKeyBox = new QGroupBox(tr("Operations"));
auto *vboxPK = new QVBoxLayout();
- auto *exportButton = new QPushButton(tr("Export Private Key (Include Subkeys)"));
+ auto *exportButton = new QPushButton(tr("Export Private Key (Include Subkey)"));
vboxPK->addWidget(exportButton);
connect(exportButton, SIGNAL(clicked()), this, SLOT(slotExportPrivateKey()));
- if(mKey.has_master_key) {
+ if (mKey.has_master_key) {
auto *editExpiresButton = new QPushButton(tr("Modify Expiration Datetime (Master Key)"));
vboxPK->addWidget(editExpiresButton);
connect(editExpiresButton, SIGNAL(clicked()), this, SLOT(slotModifyEditDatetime()));
+ auto hBoxLayout = new QHBoxLayout();
auto *keyServerOperaButton = new QPushButton(tr("Key Server Operation (Pubkey)"));
keyServerOperaButton->setStyleSheet("text-align:center;");
- vboxPK->addWidget(keyServerOperaButton);
+
+ auto *revokeCertGenButton = new QPushButton(tr("Generate Revoke Certificate"));
+ revokeCertGenButton->setDisabled(true);
+ connect(revokeCertGenButton, SIGNAL(clicked()), this, SLOT(slotGenRevokeCert()));
+
+ hBoxLayout->addWidget(keyServerOperaButton);
+ hBoxLayout->addWidget(revokeCertGenButton);
+
+ vboxPK->addLayout(hBoxLayout);
connect(keyServerOperaButton, SIGNAL(clicked()), this, SLOT(slotModifyEditDatetime()));
// Set Menu
@@ -152,8 +163,6 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
privKeyBox->setLayout(vboxPK);
mvbox->addWidget(privKeyBox);
-
-
}
if ((mKey.expired) || (mKey.revoked)) {
@@ -169,7 +178,7 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
expLabel->setText(tr("Warning: The Master Key has been revoked"));
}
- iconLabel->setPixmap(pixmap.scaled(24,24,Qt::KeepAspectRatio));
+ iconLabel->setPixmap(pixmap.scaled(24, 24, Qt::KeepAspectRatio));
QFont font = expLabel->font();
font.setBold(true);
expLabel->setFont(font);
@@ -179,10 +188,11 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
mvbox->addLayout(expBox);
}
+ mvbox->setContentsMargins(0, 0, 0, 0);
+
connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshKeyInfo()));
slotRefreshKeyInfo();
-
setAttribute(Qt::WA_DeleteOnClose, true);
setLayout(mvbox);
}
@@ -190,22 +200,23 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
void KeyPairDetailTab::slotExportPrivateKey() {
// Show a information box with explanation about private key
int ret = QMessageBox::information(this, tr("Exporting private Key"),
- tr("<h3>You are about to export your <font color=\"red\">PRIVATE KEY</font>!</h3>\n"
- "This is NOT your Public Key, so DON'T give it away.<br />"
- "Do you REALLY want to export your PRIVATE KEY?"),
+ "<h3>" + tr("You are about to export your") + "<font color=\"red\">" +
+ tr("PRIVATE KEY") + "</font>!</h3>\n" +
+ tr("This is NOT your Public Key, so DON'T give it away.") + "<br />" +
+ tr("Do you REALLY want to export your PRIVATE KEY?"),
QMessageBox::Cancel | QMessageBox::Ok);
// export key, if ok was clicked
if (ret == QMessageBox::Ok) {
auto *keyArray = new QByteArray();
- if(!mCtx->exportSecretKey(mKey, keyArray)) {
- QMessageBox::critical(this, "Error", "An error occurred during the export operation.");
- return;
- }
+ if (!mCtx->exportSecretKey(mKey, keyArray)) {
+ QMessageBox::critical(this, "Error", "An error occurred during the export operation.");
+ return;
+ }
auto &key = mCtx->getKeyById(*keyid);
- QString fileString = key.name + " " +key.email + "(" +
+ QString fileString = key.name + " " + key.email + "(" +
key.id + ")_secret.asc";
QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString,
tr("Key Files") + " (*.asc *.txt);;All Files (*)");
@@ -251,13 +262,13 @@ void KeyPairDetailTab::slotRefreshKeyInfo() {
QString usage;
QTextStream usage_steam(&usage);
- if(mKey.can_certify)
+ if (mKey.can_certify)
usage_steam << "Cert ";
- if(mKey.can_encrypt)
+ if (mKey.can_encrypt)
usage_steam << "Encr ";
- if(mKey.can_sign)
+ if (mKey.can_sign)
usage_steam << "Sign ";
- if(mKey.can_authenticate)
+ if (mKey.can_authenticate)
usage_steam << "Auth ";
usageVarLabel->setText(usage);
@@ -265,13 +276,13 @@ void KeyPairDetailTab::slotRefreshKeyInfo() {
QString actualUsage;
QTextStream actual_usage_steam(&actualUsage);
- if(GpgME::GpgContext::checkIfKeyCanCert(mKey))
+ if (GpgME::GpgContext::checkIfKeyCanCert(mKey))
actual_usage_steam << "Cert ";
- if(GpgME::GpgContext::checkIfKeyCanEncr(mKey))
+ if (GpgME::GpgContext::checkIfKeyCanEncr(mKey))
actual_usage_steam << "Encr ";
- if(GpgME::GpgContext::checkIfKeyCanSign(mKey))
+ if (GpgME::GpgContext::checkIfKeyCanSign(mKey))
actual_usage_steam << "Sign ";
- if(GpgME::GpgContext::checkIfKeyCanAuth(mKey))
+ if (GpgME::GpgContext::checkIfKeyCanAuth(mKey))
actual_usage_steam << "Auth ";
actualUsageVarLabel->setText(actualUsage);
@@ -301,7 +312,7 @@ void KeyPairDetailTab::slotRefreshKeyInfo() {
void KeyPairDetailTab::createKeyServerOperaMenu() {
keyServerOperaMenu = new QMenu(this);
- auto *uploadKeyPair = new QAction(tr("Upload Key Pair"), this);
+ auto *uploadKeyPair = new QAction(tr("Upload Key Pair to Key Server"), this);
connect(uploadKeyPair, SIGNAL(triggered()), this, SLOT(slotUploadKeyToServer()));
auto *updateKeyPair = new QAction(tr("Update Key Pair"), this);
connect(updateKeyPair, SIGNAL(triggered()), this, SLOT(slotUpdateKeyToServer()));
@@ -325,3 +336,21 @@ void KeyPairDetailTab::slotUpdateKeyToServer() {
dialog->slotImportKey(keys);
}
+void KeyPairDetailTab::slotGenRevokeCert() {
+ auto mOutputFileName = QFileDialog::getSaveFileName(this, tr("Generate revocation certificate"),
+ QString(),
+ QStringLiteral("%1 (*.rev)").arg(
+ tr("Revocation Certificates")));
+
+ auto process = mCtx->generateRevokeCert(mKey, mOutputFileName);
+
+ auto *dialog = new WaitingDialog("Generating", this);
+
+ while (process->state() == QProcess::Running) {
+ QApplication::processEvents();
+ }
+
+ dialog->close();
+
+}
+
diff --git a/src/ui/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/keypair_details/KeyPairSubkeyTab.cpp
index 70c7e4b8..74b52284 100644
--- a/src/ui/keypair_details/KeyPairSubkeyTab.cpp
+++ b/src/ui/keypair_details/KeyPairSubkeyTab.cpp
@@ -47,6 +47,7 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW
auto subkeyListLayout = new QGridLayout();
subkeyListLayout->addWidget(subkeyList, 0, 0);
subkeyListLayout->addLayout(uidButtonsLayout, 1, 0);
+ subkeyListLayout->setContentsMargins(0, 10, 0, 0);
auto *subkeyDetailLayout = new QGridLayout();
@@ -79,6 +80,7 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW
subkeyDetailLayout->addWidget(fingerPrintVarLabel, 7, 1);
listBox->setLayout(subkeyListLayout);
+ listBox->setContentsMargins(0, 5, 0, 0);
detailBox->setLayout(subkeyDetailLayout);
baseLayout->addWidget(listBox);
@@ -89,6 +91,8 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW
connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshSubkeyList()));
connect(subkeyList, SIGNAL(itemSelectionChanged()), this, SLOT(slotRefreshSubkeyDetail()));
+ baseLayout->setContentsMargins(0, 0, 0, 0);
+
setLayout(baseLayout);
setAttribute(Qt::WA_DeleteOnClose, true);
diff --git a/src/ui/keypair_details/KeyPairUIDTab.cpp b/src/ui/keypair_details/KeyPairUIDTab.cpp
index 51f188bd..2954aadb 100644
--- a/src/ui/keypair_details/KeyPairUIDTab.cpp
+++ b/src/ui/keypair_details/KeyPairUIDTab.cpp
@@ -52,21 +52,24 @@ KeyPairUIDTab::KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget
gridLayout->addWidget(uidList, 0, 0);
gridLayout->addLayout(uidButtonsLayout, 1, 0);
+ gridLayout->setContentsMargins(0, 10, 0, 0);
auto uidGroupBox = new QGroupBox();
uidGroupBox->setLayout(gridLayout);
- uidGroupBox->setTitle("UIDs");
+ uidGroupBox->setTitle(tr("UIDs"));
auto signGridLayout = new QGridLayout();
signGridLayout->addWidget(sigList, 0, 0);
+ signGridLayout->setContentsMargins(0, 10, 0, 0);
auto signGroupBox = new QGroupBox();
signGroupBox->setLayout(signGridLayout);
- signGroupBox->setTitle("Signature of Selected UID");
+ signGroupBox->setTitle(tr("Signature of Selected UID"));
auto vboxLayout = new QVBoxLayout();
vboxLayout->addWidget(uidGroupBox);
vboxLayout->addWidget(signGroupBox);
+ vboxLayout->setContentsMargins(0, 0, 0, 0);
connect(addUIDButton, SIGNAL(clicked(bool)), this, SLOT(slotAddUID()));
connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshUIDList()));
diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp
index 36d8f363..4bcee080 100644
--- a/src/ui/main_window/MainWindowSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowSlotFunction.cpp
@@ -23,6 +23,7 @@
*/
#include "MainWindow.h"
+#include "ui/SendMailDialog.h"
void MainWindow::slotEncrypt() {
@@ -58,12 +59,12 @@ void MainWindow::slotEncrypt() {
auto thread = QThread::create([&]() {
error = mCtx->encrypt(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, &result);
});
-
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
+ auto *dialog = new WaitingDialog(tr("Encrypting"), this);
- while(thread->isRunning()) {
+ while (thread->isRunning()) {
QApplication::processEvents();
}
@@ -83,6 +84,19 @@ void MainWindow::slotEncrypt() {
else
infoBoard->slotRefresh(reportText, INFO_ERROR_WARN);
+ if (resultAnalyse->getStatus() >= 0) {
+ infoBoard->resetOptionActionsMenu();
+ infoBoard->addOptionalAction("Send Mail", [this]() {
+ if(settings.value("sendMail/enable", false).toBool())
+ new SendMailDialog(edit->curTextPage()->toPlainText(), this);
+ else {
+ QMessageBox::warning(nullptr,
+ tr("Function Disabled"),
+ tr("Please go to the settings interface to enable and configure this function."));
+ }
+ });
+ }
+
delete resultAnalyse;
} else if (edit->slotCurPageFileTreeView() != nullptr) {
this->slotFileEncrypt();
@@ -118,7 +132,19 @@ void MainWindow::slotSign() {
gpgme_sign_result_t result = nullptr;
- auto error = mCtx->sign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, false, &result);
+ gpgme_error_t error;
+ auto thread = QThread::create([&]() {
+ error = mCtx->sign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, false, &result);
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
+
+ auto *dialog = new WaitingDialog(tr("Signing"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+ dialog->close();
+
infoBoard->associateTextEdit(edit->curTextPage());
edit->slotFillTextEditWithText(QString::fromUtf8(*tmp));
@@ -154,10 +180,11 @@ void MainWindow::slotDecrypt() {
// try decrypt, if fail do nothing, especially don't replace text
error = mCtx->decrypt(text, decrypted, &result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Decrypting"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
@@ -213,13 +240,13 @@ void MainWindow::slotVerify() {
auto thread = QThread::create([&]() {
error = mCtx->verify(&text, nullptr, &result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Verifying"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
-
dialog->close();
auto resultAnalyse = new VerifyResultAnalyse(mCtx, error, result);
@@ -268,27 +295,27 @@ void MainWindow::slotEncryptSign() {
if (!key_can_sign && !key_can_encr) {
QMessageBox::critical(nullptr,
- tr("Invalid KeyPair"),
- tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>")
- + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid);
+ tr("Invalid KeyPair"),
+ tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>")
+ + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid);
return;
}
- if(key_can_sign) can_sign = true;
- if(key_can_encr) can_encr = true;
+ if (key_can_sign) can_sign = true;
+ if (key_can_encr) can_encr = true;
}
- if(!can_encr) {
- QMessageBox::critical(nullptr,
- tr("Incomplete Operation"),
- tr("None of the selected key pairs can provide the encryption function."));
- return;
+ if (!can_encr) {
+ QMessageBox::critical(nullptr,
+ tr("Incomplete Operation"),
+ tr("None of the selected key pairs can provide the encryption function."));
+ return;
}
- if(!can_sign) {
- QMessageBox::warning(nullptr,
- tr("Incomplete Operation"),
- tr("None of the selected key pairs can provide the signature function."));
+ if (!can_sign) {
+ QMessageBox::warning(nullptr,
+ tr("Incomplete Operation"),
+ tr("None of the selected key pairs can provide the signature function."));
}
auto *tmp = new QByteArray();
@@ -300,18 +327,19 @@ void MainWindow::slotEncryptSign() {
gpgme_error_t error;
auto thread = QThread::create([&]() {
error = mCtx->encryptSign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, &encr_result,
- &sign_result);
+ &sign_result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Encrypting and Signing"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
dialog->close();
- if(gpgme_err_code(error) == GPG_ERR_NO_ERROR) {
+ if (gpgme_err_code(error) == GPG_ERR_NO_ERROR) {
auto *tmp2 = new QString(*tmp);
edit->slotFillTextEditWithText(*tmp2);
}
@@ -330,6 +358,19 @@ void MainWindow::slotEncryptSign() {
else
infoBoard->slotRefresh(reportText, INFO_ERROR_WARN);
+ if (status >= 0) {
+ infoBoard->resetOptionActionsMenu();
+ infoBoard->addOptionalAction("Send Mail", [this]() {
+ if(settings.value("sendMail/enable", false).toBool())
+ new SendMailDialog(edit->curTextPage()->toPlainText(), this);
+ else {
+ QMessageBox::warning(nullptr,
+ tr("Function Disabled"),
+ tr("Please go to the settings interface to enable and configure this function."));
+ }
+ });
+ }
+
delete resultAnalyseEncr;
delete resultAnalyseSign;
} else if (edit->slotCurPageFileTreeView() != nullptr) {
@@ -354,10 +395,11 @@ void MainWindow::slotDecryptVerify() {
auto thread = QThread::create([&]() {
error = mCtx->decryptVerify(text, decrypted, &d_result, &v_result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Decrypting and Verifying"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
@@ -495,22 +537,27 @@ void MainWindow::slotFileEncrypt() {
}
}
- try {
- gpgme_encrypt_result_t result;
+ gpgme_encrypt_result_t result;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
+ gpgme_error_t error;
+ bool if_error = false;
+ auto thread = QThread::create([&]() {
+ try {
error = GpgFileOpera::encryptFile(mCtx, keys, path, &result);
- });
- thread->start();
-
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
- dialog->close();
+ auto *dialog = new WaitingDialog(tr("Encrypting"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+ dialog->close();
+ if (!if_error) {
auto resultAnalyse = new EncryptResultAnalyse(error, result);
auto &reportText = resultAnalyse->getResultReport();
infoBoard->associateTabWidget(edit->tabWidget);
@@ -526,11 +573,10 @@ void MainWindow::slotFileEncrypt() {
delete resultAnalyse;
fileTreeView->update();
-
- } catch (const std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
+ return;
}
-
}
void MainWindow::slotFileDecrypt() {
@@ -572,21 +618,28 @@ void MainWindow::slotFileDecrypt() {
return;
}
- try {
- gpgme_decrypt_result_t result;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
- error = GpgFileOpera::decryptFile(mCtx, path, &result);
- });
- thread->start();
+ gpgme_decrypt_result_t result;
+ gpgme_error_t error;
+ bool if_error = false;
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ auto thread = QThread::create([&]() {
+ try {
+ error = GpgFileOpera::decryptFile(mCtx, path, &result);
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
- dialog->close();
+ auto *dialog = new WaitingDialog("Decrypting", this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ dialog->close();
+ if (!if_error) {
auto resultAnalyse = new DecryptResultAnalyse(mCtx, error, result);
auto &reportText = resultAnalyse->getResultReport();
infoBoard->associateTabWidget(edit->tabWidget);
@@ -602,7 +655,7 @@ void MainWindow::slotFileDecrypt() {
delete resultAnalyse;
fileTreeView->update();
- } catch (const std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
return;
}
@@ -661,20 +714,28 @@ void MainWindow::slotFileSign() {
}
}
- try {
- gpgme_sign_result_t result;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
- error = GpgFileOpera::signFile(mCtx, keys, path, &result);
- });
- thread->start();
+ gpgme_sign_result_t result;
+ gpgme_error_t error;
+ bool if_error = false;
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ auto thread = QThread::create([&]() {
+ try {
+ error = GpgFileOpera::signFile(mCtx, keys, path, &result);
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
- dialog->close();
+ auto *dialog = new WaitingDialog(tr("Signing"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ dialog->close();
+
+ if (!if_error) {
auto resultAnalyse = new SignResultAnalyse(error, result);
auto &reportText = resultAnalyse->getResultReport();
@@ -692,8 +753,9 @@ void MainWindow::slotFileSign() {
fileTreeView->update();
- } catch (const std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
+ return;
}
fileTreeView->update();
@@ -709,11 +771,10 @@ void MainWindow::slotFileVerify() {
QString signFilePath, dataFilePath;
- if(fileInfo.suffix() == "gpg") {
+ if (fileInfo.suffix() == "gpg") {
dataFilePath = path;
signFilePath = path;
- }
- else if (fileInfo.suffix() == "sig") {
+ } else if (fileInfo.suffix() == "sig") {
int pos = path.lastIndexOf(QChar('.'));
dataFilePath = path.left(pos);
signFilePath = path;
@@ -743,21 +804,22 @@ void MainWindow::slotFileVerify() {
gpgme_error_t error;
bool if_error = false;
auto thread = QThread::create([&]() {
- try{
+ try {
error = GpgFileOpera::verifyFile(mCtx, dataFilePath, &result);
} catch (const std::runtime_error &e) {
if_error = true;
}
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Verifying"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
dialog->close();
- if(!if_error) {
+ if (!if_error) {
auto resultAnalyse = new VerifyResultAnalyse(mCtx, error, result);
auto &reportText = resultAnalyse->getResultReport();
infoBoard->associateTabWidget(edit->tabWidget);
@@ -832,45 +894,52 @@ void MainWindow::slotFileEncryptSign() {
if (!key_can_sign && !key_can_encr) {
QMessageBox::critical(nullptr,
- tr("Invalid KeyPair"),
- tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>")
- + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid);
+ tr("Invalid KeyPair"),
+ tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>")
+ + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid);
return;
}
- if(key_can_sign) can_sign = true;
- if(key_can_encr) can_encr = true;
+ if (key_can_sign) can_sign = true;
+ if (key_can_encr) can_encr = true;
}
- if(!can_encr) {
- QMessageBox::critical(nullptr,
- tr("Incomplete Operation"),
- tr("None of the selected key pairs can provide the encryption function."));
- return;
+ if (!can_encr) {
+ QMessageBox::critical(nullptr,
+ tr("Incomplete Operation"),
+ tr("None of the selected key pairs can provide the encryption function."));
+ return;
}
- if(!can_sign) {
- QMessageBox::warning(nullptr,
- tr("Incomplete Operation"),
- tr("None of the selected key pairs can provide the signature function."));
+ if (!can_sign) {
+ QMessageBox::warning(nullptr,
+ tr("Incomplete Operation"),
+ tr("None of the selected key pairs can provide the signature function."));
}
- try {
+ gpgme_encrypt_result_t encr_result = nullptr;
+ gpgme_sign_result_t sign_result = nullptr;
- gpgme_encrypt_result_t encr_result = nullptr;
- gpgme_sign_result_t sign_result = nullptr;
+ gpgme_error_t error;
+ bool if_error = false;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
+ auto thread = QThread::create([&]() {
+ try {
error = GpgFileOpera::encryptSignFile(mCtx, keys, path, &encr_result, &sign_result);
- });
- thread->start();
-
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
- dialog->close();
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
+
+ WaitingDialog *dialog = new WaitingDialog(tr("Encrypting and Signing"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+ dialog->close();
+
+ if (!if_error) {
auto resultAnalyseEncr = new EncryptResultAnalyse(error, encr_result);
auto resultAnalyseSign = new SignResultAnalyse(error, sign_result);
@@ -891,8 +960,9 @@ void MainWindow::slotFileEncryptSign() {
fileTreeView->update();
- } catch (std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
+ return;
}
}
@@ -924,22 +994,30 @@ void MainWindow::slotFileDecryptVerify() {
outFileName = path + ".out";
}
- try {
+ gpgme_decrypt_result_t d_result = nullptr;
+ gpgme_verify_result_t v_result = nullptr;
- gpgme_decrypt_result_t d_result = nullptr;
- gpgme_verify_result_t v_result = nullptr;
+ gpgme_error_t error;
+ bool if_error = false;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
+ auto thread = QThread::create([&]() {
+ try {
error = GpgFileOpera::decryptVerifyFile(mCtx, path, &d_result, &v_result);
- });
- thread->start();
-
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
- dialog->close();
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
+
+
+ auto *dialog = new WaitingDialog(tr("Decrypting and Verifying"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+ dialog->close();
+
+ if (!if_error) {
infoBoard->associateFileTreeView(edit->curFilePage());
auto resultAnalyseDecrypt = new DecryptResultAnalyse(mCtx, error, d_result);
@@ -964,7 +1042,7 @@ void MainWindow::slotFileDecryptVerify() {
delete resultAnalyseVerify;
fileTreeView->update();
- } catch (std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
return;
}
@@ -997,3 +1075,21 @@ void MainWindow::slotFileVerifyCustom() {
void MainWindow::slotOpenFile(QString &path) {
edit->slotOpenFile(path);
}
+
+void MainWindow::slotVersionUpgrade(const QString &currentVersion, const QString &latestVersion) {
+ if(currentVersion < latestVersion) {
+ QMessageBox::warning(this,
+ tr("Outdated Version"),
+ tr("This version(%1) is out of date, please update the latest version in time. ").arg(
+ currentVersion)
+ + tr("You can download the latest version(%1) on Github Releases Page.<br/>").arg(
+ latestVersion));
+ } else if(currentVersion > latestVersion) {
+ QMessageBox::warning(this,
+ tr("Unreleased Version"),
+ tr("This version(%1) has not been officially released and is not recommended for use in a production environment. <br/>").arg(
+ currentVersion)
+ + tr("You can download the latest version(%1) on Github Releases Page.<br/>").arg(
+ latestVersion));
+ }
+}
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index 189ead53..7065e41c 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -25,7 +25,11 @@
#include "MainWindow.h"
void MainWindow::slotAbout() {
- new AboutDialog(this);
+ new AboutDialog(0, this);
+}
+
+void MainWindow::slotCheckUpdate() {
+ new AboutDialog(2, this);
}
void MainWindow::slotSetStatusBarText(const QString &text) {
@@ -141,13 +145,6 @@ void MainWindow::slotOpenSettingsDialog() {
importButton->setToolButtonStyle(buttonStyle);
fileEncButton->setToolButtonStyle(buttonStyle);
- // Mime-settings
- if (settings.value("mime/parseMime").toBool()) {
- createAttachmentDock();
- } else if (attachmentDockCreated) {
- closeAttachmentDock();
- }
-
// restart mainwindow if necessary
if (getRestartNeeded()) {
if (edit->maybeSaveAnyTab()) {
diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp
index 233a0927..21f6e3b7 100644
--- a/src/ui/main_window/MainWindowUI.cpp
+++ b/src/ui/main_window/MainWindowUI.cpp
@@ -209,18 +209,27 @@ void MainWindow::createActions() {
importKeyFromEditAct->setToolTip(tr("Import New Key From Editor"));
connect(importKeyFromEditAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromEdit()));
- openKeyManagementAct = new QAction(tr("Manage &keys"), this);
+ openKeyManagementAct = new QAction(tr("Manage &Keys"), this);
openKeyManagementAct->setIcon(QIcon(":keymgmt.png"));
openKeyManagementAct->setToolTip(tr("Open Keymanagement"));
connect(openKeyManagementAct, SIGNAL(triggered()), this, SLOT(slotOpenKeyManagement()));
- /* About Menu
+ /*
+ * About Menu
*/
aboutAct = new QAction(tr("&About"), this);
aboutAct->setIcon(QIcon(":help.png"));
aboutAct->setToolTip(tr("Show the application's About box"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(slotAbout()));
+ /*
+ * Check Update Menu
+ */
+ checkUpdateAct = new QAction(tr("&Check for Updates"), this);
+ checkUpdateAct->setIcon(QIcon(":help.png"));
+ checkUpdateAct->setToolTip(tr("Check for updates"));
+ connect(checkUpdateAct, SIGNAL(triggered()), this, SLOT(slotCheckUpdate()));
+
startWizardAct = new QAction(tr("Open &Wizard"), this);
startWizardAct->setToolTip(tr("Open the wizard"));
connect(startWizardAct, SIGNAL(triggered()), this, SLOT(slotStartWizard()));
@@ -231,8 +240,8 @@ void MainWindow::createActions() {
appendSelectedKeysAct->setToolTip(tr("Append The Selected Keys To Text in Editor"));
connect(appendSelectedKeysAct, SIGNAL(triggered()), this, SLOT(slotAppendSelectedKeys()));
- copyMailAddressToClipboardAct = new QAction(tr("Copy EMail-address"), this);
- copyMailAddressToClipboardAct->setToolTip(tr("Copy selected EMailaddress to clipboard"));
+ copyMailAddressToClipboardAct = new QAction(tr("Copy Email"), this);
+ copyMailAddressToClipboardAct->setToolTip(tr("Copy selected Email to clipboard"));
connect(copyMailAddressToClipboardAct, SIGNAL(triggered()), this, SLOT(slotCopyMailAddressToClipboard()));
// TODO: find central place for shared actions, to avoid code-duplication with keymgmt.cpp
@@ -247,6 +256,7 @@ void MainWindow::createActions() {
uploadKeyToServerAct = new QAction(tr("Upload Public Key(s) To Server"), this);
uploadKeyToServerAct->setToolTip(tr("Upload The Selected Public Keys To Server"));
connect(uploadKeyToServerAct, SIGNAL(triggered()), this, SLOT(uploadKeyToServer()));
+
/* Key-Shortcuts for Tab-Switchung-Action
*/
switchTabUpAct = new QAction(this);
@@ -339,6 +349,7 @@ void MainWindow::createMenus() {
helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(startWizardAct);
helpMenu->addSeparator();
+ helpMenu->addAction(checkUpdateAct);
helpMenu->addAction(aboutAct);
}
@@ -436,26 +447,4 @@ void MainWindow::createDockWindows() {
infoBoardDock->setWidget(infoBoard);
infoBoardDock->widget()->layout()->setContentsMargins(0, 0, 0, 0);
viewMenu->addAction(infoBoardDock->toggleViewAction());
-
- /* Attachments-Dockwindow
- */
- if (settings.value("mime/parseMime").toBool()) {
- createAttachmentDock();
- }
-}
-
-void MainWindow::createAttachmentDock() {
- if (attachmentDockCreated) {
- return;
- }
- mAttachments = new Attachments();
- attachmentDock = new QDockWidget(tr("Attached files:"), this);
- attachmentDock->setObjectName("AttachmentDock");
- attachmentDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
- addDockWidget(Qt::LeftDockWidgetArea, attachmentDock);
- attachmentDock->setWidget(mAttachments);
- // hide till attachment is decrypted
- viewMenu->addAction(attachmentDock->toggleViewAction());
- attachmentDock->hide();
- attachmentDockCreated = true;
}
diff --git a/src/ui/widgets/Attachments.cpp b/src/ui/widgets/Attachments.cpp
deleted file mode 100644
index 8f741f66..00000000
--- a/src/ui/widgets/Attachments.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-/* TODO:
- * - check content encoding (base64 / quoted-printable) and apply appropriate opperation (maybe already in mime.cpp)
- * - check memory usage, use less copy operations / more references
- * - possibility to clear attachment-view , e.g. with decryption or encrypting a new message
- * - save all: like in thunderbird, one folder, all files go there
- */
-
-/*
- * - save, delete (clear) all
- * - each line save & clear button
- * - attached files to view-menu
- * - also an open button, whichs should save file to tmp-folder, and open with correct app (via QDesktopServices)
- */
-
-
-#include "ui/widgets/Attachments.h"
-
-Attachments::Attachments(QWidget *parent)
- : QWidget(parent) {
- table = new AttachmentTableModel(this);
-
- tableView = new QTableView;
- tableView->setModel(table);
- tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
- // only one entry should be selected at time
- tableView->setSelectionMode(QAbstractItemView::SingleSelection);
- tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
- tableView->setFocusPolicy(Qt::NoFocus);
- tableView->setAlternatingRowColors(true);
- tableView->verticalHeader()->hide();
- tableView->setShowGrid(false);
- tableView->setColumnWidth(0, 300);
- tableView->horizontalHeader()->setStretchLastSection(true);
-
- auto *layout = new QVBoxLayout;
- layout->addWidget(tableView);
- layout->setContentsMargins(0, 0, 0, 0);
- setLayout(layout);
- createActions();
-
-}
-
-void Attachments::contextMenuEvent(QContextMenuEvent *event) {
- QMenu menu(this);
- menu.addAction(saveFileAct);
- // enable open with only if allowed by user
- if (settings.value("mime/openAttachment").toBool())
- menu.addAction(openFileAct);
-
- menu.exec(event->globalPos());
-}
-
-void Attachments::createActions() {
- saveFileAct = new QAction(tr("Save File"), this);
- saveFileAct->setToolTip(tr("Save this file"));
- saveFileAct->setIcon(QIcon(":filesave.png"));
- connect(saveFileAct, SIGNAL(triggered()), this, SLOT(slotSaveFile()));
-
- openFileAct = new QAction(tr("Open File"), this);
- openFileAct->setToolTip(tr("Open this file"));
- openFileAct->setIcon(QIcon(":fileopen.png"));
- connect(openFileAct, SIGNAL(triggered()), this, SLOT(slotOpenFile()));
-
-}
-
-void Attachments::slotSaveFile() {
-
- QModelIndexList indexes = tableView->selectionModel()->selection().indexes();
-
- if (indexes.empty()) {
- return;
- }
-
- // only singe-selection possible now: TODO: foreach
- MimePart mp = table->getMimePart(indexes.at(0).row());
- QString filename = mp.header.getParam("Content-Type", "name");
- // TODO: find out why filename is quoted
- filename.chop(1);
- filename.remove(0, 1);
- // TODO: check if really base64
- saveByteArrayToFile(QByteArray::fromBase64(mp.body), filename);
-
-}
-
-void Attachments::saveByteArrayToFile(QByteArray outBuffer, QString filename) {
-
- //QString path="";
- QString path = std::move(filename);
- QString outfileName = QFileDialog::getSaveFileName(this, tr("Save File"), path);
-
- if (outfileName.isEmpty()) return;
-
- QFile outfile(outfileName);
- if (!outfile.open(QFile::WriteOnly)) {
- QMessageBox::warning(this, tr("File"),
- tr("Cannot write file %1:\n%2.")
- .arg(outfileName)
- .arg(outfile.errorString()));
- return;
- }
-
- QDataStream out(&outfile);
- out.writeRawData(outBuffer.data(), outBuffer.length());
- outfile.close();
-}
-
-/**
- * WIP: TODO:
- * - create attachments dir if not existing
- * - ask for cleanup of dir on exit
- * - remove code-duplication with saveByteArrayToFile
- */
-void Attachments::slotOpenFile() {
-
- // TODO: make attachmentdir constant or configurable
- QString attachmentDir = qApp->applicationDirPath() + "/attachments/";
- //QDir p = QDir(qApp->applicationDirPath() + "/attachments/");
- if (!QDir(attachmentDir).exists()) {
- QDir().mkpath(attachmentDir);
- }
-
- QModelIndexList indexes = tableView->selectionModel()->selection().indexes();
- MimePart mp = table->getMimePart(indexes.at(0).row());
-
-// qDebug() << "mime: " << mp.header.getValue("Content-Type");
-
- QString filename = mp.header.getParam("Content-Type", "name");
- // TODO: find out why filename is quoted
-// qDebug() << "file: " << filename;
- filename.chop(1);
- filename.remove(0, 1);
- filename.prepend(attachmentDir);
-
- // qDebug() << "file: " << filename;
- QByteArray outBuffer = QByteArray::fromBase64(mp.body);
-
-
- QFile outfile(filename);
- if (!outfile.open(QFile::WriteOnly)) {
- QMessageBox::warning(this, tr("File"),
- tr("Cannot write file %1:\n%2.")
- .arg(filename)
- .arg(outfile.errorString()));
- return;
- }
-
- QDataStream out(&outfile);
- out.writeRawData(outBuffer.data(), outBuffer.length());
- outfile.close();
- QDesktopServices::openUrl(QUrl("file://" + filename, QUrl::TolerantMode));
-}
-
-void Attachments::addMimePart(MimePart *mp) {
- table->add(*mp);
-}
-
diff --git a/src/ui/widgets/EditorPage.cpp b/src/ui/widgets/EditorPage.cpp
index 8a51b721..05d5cbea 100644
--- a/src/ui/widgets/EditorPage.cpp
+++ b/src/ui/widgets/EditorPage.cpp
@@ -42,6 +42,9 @@ EditorPage::EditorPage(QString filePath, QWidget *parent) : QWidget(parent),
setAttribute(Qt::WA_DeleteOnClose);
textPage->setFocus();
+ // Front in same width
+ this->setFont({"Courier"});
+
connect(textPage, SIGNAL(textChanged()), this, SLOT(formatGpgHeader()));
}
diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp
index bab6cf68..b9602d58 100644
--- a/src/ui/widgets/FilePage.cpp
+++ b/src/ui/widgets/FilePage.cpp
@@ -46,15 +46,33 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
createPopupMenu();
- upLevelButton = new QPushButton("Up");
+
+ upLevelButton = new QPushButton();
connect(upLevelButton, SIGNAL(clicked(bool)), this, SLOT(slotUpLevel()));
+ QString buttonStyle = "QPushButton{border:none;background-color:rgba(255, 255, 255,100);}";
+
+
+ auto upPixmap = QPixmap(":up.png");
+ upPixmap = upPixmap.scaled(18, 18, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ QIcon upButtonIcon(upPixmap);
+ upLevelButton->setIcon(upButtonIcon);
+ upLevelButton->setIconSize(upPixmap.rect().size());
+ upLevelButton->setStyleSheet(buttonStyle);
+
refreshButton = new QPushButton("Refresh");
connect(refreshButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath()));
- goPathButton = new QPushButton("Go");
+ goPathButton = new QPushButton();
connect(goPathButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath()));
+ auto updatePixmap = QPixmap(":refresh.png");
+ updatePixmap = updatePixmap.scaled(18, 18, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ QIcon updateButtonIcon(updatePixmap);
+ goPathButton->setIcon(updateButtonIcon);
+ goPathButton->setIconSize(updatePixmap.rect().size());
+ goPathButton->setStyleSheet(buttonStyle);
+
pathEdit = new QLineEdit();
pathEdit->setText(dirModel->rootPath());
@@ -62,7 +80,7 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
menuLayout->addWidget(upLevelButton);
menuLayout->setStretchFactor(upLevelButton, 1);
menuLayout->addWidget(pathEdit);
- menuLayout->setStretchFactor(pathEdit, 8);
+ menuLayout->setStretchFactor(pathEdit, 10);
menuLayout->addWidget(goPathButton);
menuLayout->setStretchFactor(goPathButton, 1);
// menuLayout->addWidget(refreshButton);
@@ -87,17 +105,22 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
}
void FilePage::fileTreeViewItemClicked(const QModelIndex &index) {
- mPath = dirModel->fileInfo(index).absoluteFilePath();
- qDebug() << "mPath" << mPath;
+ selectedPath = dirModel->fileInfo(index).absoluteFilePath();
+ qDebug() << "selectedPath" << selectedPath;
}
void FilePage::slotUpLevel() {
QModelIndex currentRoot = dirTreeView->rootIndex();
- mPath = dirModel->fileInfo(currentRoot.parent()).absoluteFilePath();
- auto fileInfo = QFileInfo(mPath);
+
+ mPath = dirModel->fileInfo(currentRoot).absoluteFilePath();
+ QDir dir(mPath);
+ dir.makeAbsolute();
+ dir.setPath(QDir::cleanPath(dir.filePath(QStringLiteral(".."))));
+ mPath = dir.absolutePath();
+ auto fileInfo = QFileInfo(dir.absolutePath());
if(fileInfo.isDir() && fileInfo.isReadable() && fileInfo.isExecutable()) {
- dirTreeView->setRootIndex(currentRoot.parent());
pathEdit->setText(mPath);
+ slotGoPath();
}
qDebug() << "Current Root mPath" << mPath;
emit pathChanged(mPath);
@@ -106,8 +129,9 @@ void FilePage::slotUpLevel() {
void FilePage::fileTreeViewItemDoubleClicked(const QModelIndex &index) {
mPath = dirModel->fileInfo(index).absoluteFilePath();
auto fileInfo = QFileInfo(mPath);
+ auto targetModelIndex = dirTreeView->model()->index(index.row(), 0, index.parent());
if(fileInfo.isDir() && fileInfo.isReadable() && fileInfo.isExecutable()) {
- dirTreeView->setRootIndex(index);
+ dirTreeView->setRootIndex(targetModelIndex);
pathEdit->setText(mPath);
}
qDebug() << "Index mPath" << mPath;
@@ -115,7 +139,7 @@ void FilePage::fileTreeViewItemDoubleClicked(const QModelIndex &index) {
}
QString FilePage::getSelected() const {
- return mPath;
+ return selectedPath;
}
void FilePage::slotGoPath() {
@@ -159,10 +183,10 @@ void FilePage::createPopupMenu() {
void FilePage::onCustomContextMenu(const QPoint &point) {
QModelIndex index = dirTreeView->indexAt(point);
- mPath = dirModel->fileInfo(index).absoluteFilePath();
- qDebug() << "Right Click" << mPath;
+ selectedPath = dirModel->fileInfo(index).absoluteFilePath();
+ qDebug() << "Right Click" << selectedPath;
if (index.isValid()) {
- QFileInfo info(mPath);
+ QFileInfo info(selectedPath);
encryptItemAct->setEnabled(info.isFile() && (info.suffix() != "gpg" && info.suffix() != "sig"));
decryptItemAct->setEnabled(info.isFile() && info.suffix() == "gpg");
signItemAct->setEnabled(info.isFile() && (info.suffix() != "gpg" && info.suffix() != "sig"));
@@ -234,3 +258,10 @@ void FilePage::slotVerifyItem() {
if(mainWindow != nullptr)
mainWindow->slotFileVerify();
}
+
+void FilePage::keyPressEvent(QKeyEvent *event) {
+ qDebug() << "Key Press" << event->key();
+ if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
+ slotGoPath();
+ }
+}
diff --git a/src/ui/widgets/InfoBoardWidget.cpp b/src/ui/widgets/InfoBoardWidget.cpp
index 33517a8e..f26917a4 100644
--- a/src/ui/widgets/InfoBoardWidget.cpp
+++ b/src/ui/widgets/InfoBoardWidget.cpp
@@ -25,7 +25,9 @@
#include "ui/widgets/InfoBoardWidget.h"
InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyList *keyList) :
- QWidget(parent), mCtx(ctx), mKeyList(keyList) {
+ QWidget(parent), mCtx(ctx), mKeyList(keyList), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
infoBoard = new QTextEdit(this);
infoBoard->setReadOnly(true);
@@ -42,7 +44,7 @@ InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyLis
detailMenu->addAction(importFromKeyserverAct);
importFromKeyserverAct->setVisible(false);
- QWidget *actionButtonMenu = new QWidget();
+ auto *actionButtonMenu = new QWidget();
actionButtonMenu->setContentsMargins(0, 0, 0, 0);
actionButtonMenu->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
actionButtonMenu->setFixedHeight(36);
@@ -52,7 +54,7 @@ InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyLis
actionButtonLayout->setSpacing(0);
actionButtonMenu->setLayout(actionButtonLayout);
- auto label = new QLabel("Optional Actions Menu");
+ auto label = new QLabel(tr("Optional Actions Menu"));
label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
label->setContentsMargins(0, 0, 0, 0);
@@ -107,7 +109,8 @@ void InfoBoardWidget::setInfoBoard(const QString &text, InfoBoardStatus verifyLa
QPalette status = infoBoard->palette();
status.setColor(QPalette::Text, color);
infoBoard->setPalette(status);
- infoBoard->setFont(QFont("Times", 10));
+ auto infoBoardFontSize = settings.value("informationBoard/fontSize", 10).toInt();
+ infoBoard->setFont(QFont("Times", infoBoardFontSize));
}
void InfoBoardWidget::slotRefresh(const QString &text, InfoBoardStatus status) {
@@ -135,13 +138,16 @@ void InfoBoardWidget::associateTabWidget(QTabWidget *tab) {
disconnect(mTextPage, SIGNAL(textChanged()), this, SLOT(slotReset()));
// if (mFileTreeView != nullptr)
// disconnect(mFileTreeView, &FilePage::pathChanged, this, &InfoBoardWidget::slotReset);
- if (mTabWidget != nullptr)
+ if (mTabWidget != nullptr) {
disconnect(mTabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(slotReset()));
+ connect(mTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(slotReset()));
+ }
mTextPage = nullptr;
mFileTreeView = nullptr;
mTabWidget = tab;
connect(tab, SIGNAL(tabBarClicked(int)), this, SLOT(slotReset()));
+ connect(tab, SIGNAL(tabCloseRequested(int)), this, SLOT(slotReset()));
}
void InfoBoardWidget::addOptionalAction(const QString &name, const std::function<void()> &action) {
diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp
index b044020a..3929868e 100644
--- a/src/ui/widgets/KeyList.cpp
+++ b/src/ui/widgets/KeyList.cpp
@@ -297,6 +297,11 @@ void KeyList::contextMenuEvent(QContextMenuEvent *event)
}
+void KeyList::addSeparator()
+{
+ popupMenu->addSeparator();
+}
+
void KeyList::addMenuAction(QAction *act)
{
popupMenu->addAction(act);
diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp
index 26cc3834..eab0f799 100644
--- a/src/ui/widgets/TextEdit.cpp
+++ b/src/ui/widgets/TextEdit.cpp
@@ -37,9 +37,6 @@ TextEdit::TextEdit(QWidget *parent) : QWidget(parent) {
layout->setSpacing(0);
setLayout(layout);
- // Front in same width
- this->setFont({"Courier"});
-
connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
SLOT(removeTab(int)));
connect(this, &TextEdit::insertTargetTextPage, this,
@@ -73,7 +70,7 @@ void TextEdit::slotNewHelpTab(const QString &title, const QString &path) const {
void TextEdit::slotNewFileTab() const {
auto *page = new FilePage(qobject_cast<QWidget *>(parent()));
- tabWidget->addTab(page, "[File Browser]");
+ tabWidget->addTab(page, "[Browser]");
tabWidget->setCurrentIndex(tabWidget->count() - 1);
connect(page, SIGNAL(pathChanged(const QString &)), this,
SLOT(slotFilePagePathChanged(const QString &)));
@@ -132,6 +129,7 @@ void TextEdit::slotInsertTargetTextPage(const QString &pagePtr,
auto *taregtTextPage = qobject_cast<EditorPage *>(it.value());
if (taregtTextPage != nullptr) {
taregtTextPage->getTextPage()->insertPlainText(text);
+ taregtTextPage->getTextPage()->document()->setModified(false);
}
}
}
@@ -164,6 +162,7 @@ void TextEdit::slotReadTargetTextPageDone(const QString &pagePtr) {
tabWidget->setTabText(index,
strippedName(taregtTextPage->getFilePath()));
}
+ taregtTextPage->getTextPage()->document()->setModified(false);
connect(taregtTextPage->getTextPage()->document(),
SIGNAL(modificationChanged(bool)), this,
SLOT(slotShowModified()));
@@ -638,13 +637,13 @@ void TextEdit::slotFilePagePathChanged(const QString &path) {
int index = tabWidget->currentIndex();
QString mPath;
QFileInfo fileInfo(path);
- QString tPath = fileInfo.path();
+ QString tPath = fileInfo.absoluteFilePath();
if (path.size() > 18) {
mPath = tPath.mid(tPath.size() - 18, 18).prepend("...");
} else {
mPath = tPath;
}
- mPath.prepend("[File Browser] ");
+ mPath.prepend("[Browser] ");
mPath.append("/");
tabWidget->setTabText(index, mPath);
}